home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / generate.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  69KB  |  2,815 lines

  1.  
  2. /*
  3.  * generate.c: initialize/create a dungeon or town level 
  4.  *
  5.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  6.  *
  7.  * This software may be copied and distributed for educational, research, and
  8.  * not for profit purposes provided that this copyright and statement are
  9.  * included in all such copies. 
  10.  */
  11.  
  12. #include "constant.h"
  13. #include "config.h"
  14. #include "types.h"
  15. #include "externs.h"
  16. #include "monster.h"
  17.  
  18. #ifdef ibm032
  19. #include <sys/types.h>
  20. #endif
  21.  
  22. #ifdef USG
  23. #if !defined(ATARIST_MWC)
  24. #ifndef __TURBOC__
  25. #include <memory.h>
  26. #else
  27. #include <mem.h>
  28. #endif
  29. #endif
  30. #endif
  31.  
  32. #ifdef __MINT__
  33. #include <string.h>
  34. #endif
  35.  
  36. /* Lets do all prototypes correctly.... -CWS */
  37. #ifndef NO_LINT_ARGS
  38. #ifdef __STDC__
  39. static void correct_dir(int *, int *, int, int, int, int);
  40. static void rand_dir(int *, int *);
  41. static void fill_cave(int);
  42. static void place_streamer(int, int);
  43. static cave_type *test_place_obj(int, int);
  44. static void place_open_door(int, int);
  45. static void place_broken_door(int, int);
  46. static void place_closed_door(int, int);
  47. static void place_locked_door(int, int);
  48. static void place_stuck_door(int, int);
  49. static void place_secret_door(int, int);
  50. static void place_door(int, int);
  51. static void place_up_stairs(int, int);
  52. static void place_down_stairs(int, int);
  53. static void place_stairs(int, int, int);
  54. static void vault_trap(int, int, int, int, int);
  55. static void vault_monster(int, int, int);
  56. static void vault_jelly(int, int);
  57. static void vault_orc(int, int, int);
  58. static void vault_troll(int, int, int);
  59. static void vault_undead(int, int);
  60. static void vault_dragon(int, int, int, int);
  61. static void vault_demon(int, int, int);
  62. static void vault_giant(int, int, int);
  63. static void build_room(int, int);
  64. static void build_type1(int, int);
  65. static void build_type5(int, int);
  66. static void build_type2(int, int);
  67. static void build_type3(int, int);
  68. static void vault_nasty(int, int, int, int, int);
  69. static void special_pit(int, int, int);
  70. static void build_tunnel(int, int, int, int);
  71. static int next_to(int, int);
  72. static void try_door(int, int);
  73. static void new_spot(int16 *, int16 *);
  74. static void build_pit(int, int);
  75. static void build_store(int, int, int);
  76. #else
  77. static void correct_dir();
  78. static void rand_dir();
  79. static void fill_cave();
  80. static void place_streamer();
  81. static cave_type *test_place_obj();
  82. static void place_open_door();
  83. static void place_broken_door();
  84. static void place_closed_door();
  85. static void place_locked_door();
  86. static void place_stuck_door();
  87. static void place_secret_door();
  88. static void place_door();
  89. static void place_up_stairs();
  90. static void place_down_stairs();
  91. static void place_stairs();
  92. static void vault_trap();
  93. static void vault_monster();
  94. static void vault_jelly();
  95. static void vault_orc();
  96. static void vault_troll();
  97. static void vault_undead();
  98. static void vault_dragon();
  99. static void vault_demon();
  100. static void vault_giant();
  101. static void build_room();
  102. static void build_type1();
  103. static void build_type5();
  104. static void build_type2();
  105. static void build_type3();
  106. static void vault_nasty();
  107. static void special_pit();
  108. static int  next_to();
  109. static void try_door();
  110. static void new_spot();
  111. static void build_pit();
  112. static void build_store();
  113. #endif
  114.  
  115. static void place_boundary();
  116. static void place_destroyed();
  117. static void blank_cave();
  118. static void cave_gen();
  119. static void tlink();
  120. static void mlink();
  121. static void town_gen();
  122. #endif
  123.  
  124. typedef struct coords {
  125.     int x, y;
  126. } coords;
  127.  
  128. static coords doorstk[100];
  129. static int    doorindex;
  130.  
  131. extern int    rating;
  132. extern int    peek;
  133.  
  134. /* Always picks a correct direction         */
  135. static void 
  136. correct_dir(rdir, cdir, y1, x1, y2, x2)
  137. int         *rdir, *cdir;
  138. register int y1, x1, y2, x2;
  139. {
  140.     if (y1 < y2)
  141.     *rdir = 1;
  142.     else if (y1 == y2)
  143.     *rdir = 0;
  144.     else
  145.     *rdir = (-1);
  146.     if (x1 < x2)
  147.     *cdir = 1;
  148.     else if (x1 == x2)
  149.     *cdir = 0;
  150.     else
  151.     *cdir = (-1);
  152.     if ((*rdir != 0) && (*cdir != 0)) {
  153.     if (randint(2) == 1)
  154.         *rdir = 0;
  155.     else
  156.         *cdir = 0;
  157.     }
  158. }
  159.  
  160.  
  161. /* Chance of wandering direction             */
  162. static void 
  163. rand_dir(rdir, cdir)
  164. int *rdir, *cdir;
  165. {
  166.     register int tmp;
  167.  
  168.     tmp = randint(4);
  169.     if (tmp < 3) {
  170.     *cdir = 0;
  171.     *rdir = (-3) + (tmp << 1);   /* tmp=1 -> *rdir=-1; tmp=2 -> *rdir=1 */
  172.     } else {
  173.     *rdir = 0;
  174.     *cdir = (-7) + (tmp << 1);   /* tmp=3 -> *cdir=-1; tmp=4 -> *cdir=1 */
  175.     }
  176. }
  177.  
  178.  
  179. /* Blanks out entire cave                -RAK-     */
  180. static void 
  181. blank_cave()
  182. {
  183. #ifndef USG
  184.     bzero((char *)&cave[0][0], sizeof(cave));
  185. #else
  186. #ifdef MAC
  187. /* On the mac, cave is a pointer, so sizeof(cave) = 4! */
  188.     (void)memset((char *)&cave[0][0], 0, sizeof(cave_type) * MAX_HEIGHT * MAX_WIDTH);
  189. #else
  190.     (void)memset((char *)&cave[0][0], 0, sizeof(cave));
  191. #endif
  192. #endif
  193. }
  194.  
  195.  
  196. /* Fills in empty spots with desired rock        -RAK-     */
  197. /* Note: 9 is a temporary value.                 */
  198. static void 
  199. fill_cave(fval)
  200. register int fval;
  201. {
  202.     register int        i, j;
  203.     register cave_type *c_ptr;
  204.  
  205. /* no need to check the border of the cave */
  206.  
  207.     for (i = cur_height - 2; i > 0; i--) {
  208.     c_ptr = &cave[i][1];
  209.     for (j = cur_width - 2; j > 0; j--) {
  210.         if ((c_ptr->fval == NULL_WALL) || (c_ptr->fval == TMP1_WALL) ||
  211.         (c_ptr->fval == TMP2_WALL))
  212.         c_ptr->fval = fval;
  213.         c_ptr++;
  214.     }
  215.     }
  216. }
  217.  
  218. /* Places indestructible rock around edges of dungeon    -RAK-     */
  219. static void 
  220. place_boundary()
  221. {
  222.     register int        i;
  223.     register cave_type *top_ptr, *bottom_ptr;
  224.  
  225.     cave_type(*left_ptr)[MAX_WIDTH];
  226.     cave_type(*right_ptr)[MAX_WIDTH];
  227.  
  228. /* put permanent wall on leftmost row and rightmost row */
  229.     left_ptr = (cave_type(*)[MAX_WIDTH]) & cave[0][0];
  230.     right_ptr = (cave_type(*)[MAX_WIDTH]) & cave[0][cur_width - 1];
  231.  
  232.     for (i = 0; i < cur_height; i++) {
  233.     ((cave_type *) left_ptr)->fval = BOUNDARY_WALL;
  234.     left_ptr++;
  235.     ((cave_type *) right_ptr)->fval = BOUNDARY_WALL;
  236.     right_ptr++;
  237.     }
  238.  
  239. /* put permanent wall on top row and bottom row */
  240.     top_ptr = &cave[0][0];
  241.     bottom_ptr = &cave[cur_height - 1][0];
  242.  
  243.     for (i = 0; i < cur_width; i++) {
  244.     top_ptr->fval = BOUNDARY_WALL;
  245.     top_ptr++;
  246.     bottom_ptr->fval = BOUNDARY_WALL;
  247.     bottom_ptr++;
  248.     }
  249. }
  250.  
  251.  
  252. /* Places "streamers" of rock through dungeon        -RAK-     */
  253. static void 
  254. place_streamer(fval, treas_chance)
  255. int fval, treas_chance;
  256. {
  257.     register int        i, tx, ty;
  258.     int                 y, x, t1, t2, dir;
  259.     register cave_type *c_ptr;
  260.  
  261. /* Choose starting point and direction         */
  262.     y = (cur_height / 2) + 11 - randint(23);
  263.     x = (cur_width / 2) + 16 - randint(33);
  264.  
  265.     dir = randint(8);           /* Number 1-4, 6-9     */
  266.     if (dir > 4)
  267.     dir = dir + 1;
  268.  
  269. /* Place streamer into dungeon             */
  270.     t1 = 2 * DUN_STR_RNG + 1;       /* Constants     */
  271.     t2 = DUN_STR_RNG + 1;
  272.     do {
  273.     for (i = 0; i < DUN_STR_DEN; i++) {
  274.         ty = y + randint(t1) - t2;
  275.         tx = x + randint(t1) - t2;
  276.         if (in_bounds(ty, tx)) {
  277.         c_ptr = &cave[ty][tx];
  278.         if (c_ptr->fval == GRANITE_WALL) {
  279.             c_ptr->fval = fval;
  280.             if (randint(treas_chance) == 1)
  281.             place_gold(ty, tx);
  282.         }
  283.         }
  284.     }
  285.     }
  286.     while (mmove(dir, &y, &x));
  287. }
  288.  
  289.  
  290. void 
  291. repl_spot(y, x, typ)           /* copied verbatim from spells.c - damn
  292.                     * thing won't find it. :( :( -DGK */
  293. int y, x, typ;
  294. {
  295.     register cave_type *c_ptr;
  296.  
  297.     c_ptr = &cave[y][x];
  298.     switch (typ) {
  299.       case 1:
  300.       case 2:
  301.       case 3:
  302.     c_ptr->fval = CORR_FLOOR;
  303.     break;
  304.       case 4:
  305.       case 7:
  306.       case 10:
  307.     c_ptr->fval = GRANITE_WALL;
  308.     break;
  309.       case 5:
  310.       case 8:
  311.       case 11:
  312.     c_ptr->fval = MAGMA_WALL;
  313.     break;
  314.       case 6:
  315.       case 9:
  316.       case 12:
  317.     c_ptr->fval = QUARTZ_WALL;
  318.     break;
  319.     }
  320.     c_ptr->pl = FALSE;
  321.     c_ptr->fm = FALSE;
  322.     c_ptr->lr = FALSE;           /* this is no longer part of a room */
  323.     if (c_ptr->tptr != 0)
  324.     (void)delete_object(y, x);
  325.     if (c_ptr->cptr > 1)
  326.     delete_monster((int)c_ptr->cptr);
  327. }
  328.  
  329.  
  330. static void 
  331. place_destroyed()
  332. {
  333.     register int y, x;
  334.     register int i, j, k;
  335.     int          n;
  336.  
  337.     for (n = 1; n <= randint(5); n++) {
  338.     x = randint(cur_width - 32) + 15;
  339.     y = randint(cur_height - 32) + 15;
  340.     for (i = (y - 15); i <= (y + 15); i++)
  341.         for (j = (x - 15); j <= (x + 15); j++)
  342.         if (in_bounds(i, j) && (cave[i][j].fval != BOUNDARY_WALL) &&
  343.             ((cave[i][j].tptr == 0) ||    /* DGK */
  344.              ((t_list[cave[i][j].tptr].tval != TV_UP_STAIR) &&
  345.               (t_list[cave[i][j].tptr].tval != TV_DOWN_STAIR) &&
  346.               (!(t_list[cave[i][j].tptr].flags2 & TR_ARTIFACT))))) {
  347.             k = distance(i, j, y, x);
  348.             if (i == char_row && j == char_col)
  349.             repl_spot(i, j, 1);
  350.             else if (k < 13)
  351.             repl_spot(i, j, (int)randint(6));
  352.             else if (k < 16)
  353.             repl_spot(i, j, (int)randint(9));
  354.         }
  355.     }
  356. }
  357.  
  358. /* Chris Tate (fixer@faxcsl.dcrt.nih.gov) - optimize this code for size!
  359.  * This code performs the common test in all of the place_* functions,
  360.  * and returns c_ptr if we can go ahead and place the object, or NULL
  361.  * if we can't.
  362.  */
  363.  
  364. static cave_type *
  365. test_place_obj(y, x)
  366. int y, x;
  367. {
  368.     cave_type *t;
  369.     int        tv;
  370.     
  371.     if (!in_bounds(y,x))
  372.     return NULL;
  373.     t = &cave[y][x];
  374.     tv = t_list[t->tptr].tval;
  375.     
  376.     if (t->tptr != 0)
  377.     if (((tv <= TV_MAX_WEAR) && (tv >= TV_MIN_WEAR) &&
  378.          (t_list[t->tptr].flags2 & TR_ARTIFACT)) ||
  379.         (tv == TV_UP_STAIR) || (tv == TV_DOWN_STAIR) ||
  380.         (tv == TV_STORE_DOOR))
  381.         return NULL;
  382.     else
  383.         delete_object(y,x); /* waste it, it's not important */
  384.     return t;
  385. }
  386.  
  387.  
  388. static void 
  389. place_open_door(y, x)
  390. int y, x;
  391. {
  392.     register int        cur_pos;
  393.     register cave_type *c_ptr;
  394.  
  395.     if (!(c_ptr = test_place_obj(y,x))) return;
  396.     cur_pos = popt();
  397.     c_ptr->tptr = cur_pos;
  398.     invcopy(&t_list[cur_pos], OBJ_OPEN_DOOR);
  399.     c_ptr->fval = CORR_FLOOR;
  400. }
  401.  
  402.  
  403. static void 
  404. place_broken_door(y, x)
  405. int y, x;
  406. {
  407.     register int        cur_pos;
  408.     register cave_type *c_ptr;
  409.  
  410.     if (!(c_ptr = test_place_obj(y,x))) return;
  411.     cur_pos = popt();
  412.     c_ptr->tptr = cur_pos;
  413.     invcopy(&t_list[cur_pos], OBJ_OPEN_DOOR);
  414.     c_ptr->fval = CORR_FLOOR;
  415.     t_list[cur_pos].p1 = 1;
  416. }
  417.  
  418.  
  419. static void 
  420. place_closed_door(y, x)
  421. int y, x;
  422. {
  423.     register int        cur_pos;
  424.     register cave_type *c_ptr;
  425.  
  426.     if (!(c_ptr = test_place_obj(y,x))) return;
  427.     cur_pos = popt();
  428.     c_ptr->tptr = cur_pos;
  429.     invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR);
  430.     c_ptr->fval = BLOCKED_FLOOR;
  431. }
  432.  
  433.  
  434. static void 
  435. place_locked_door(y, x)
  436. int y, x;
  437. {
  438.     register int        cur_pos;
  439.     register cave_type *c_ptr;
  440.  
  441.     if (!(c_ptr = test_place_obj(y,x))) return;
  442.     cur_pos = popt();
  443.     c_ptr->tptr = cur_pos;
  444.     invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR);
  445.     c_ptr->fval = BLOCKED_FLOOR;
  446.     t_list[cur_pos].p1 = randint(10) + 10;
  447. }
  448.  
  449.  
  450. static void 
  451. place_stuck_door(y, x)
  452. int y, x;
  453. {
  454.     register int        cur_pos;
  455.     register cave_type *c_ptr;
  456.  
  457.     if (!(c_ptr = test_place_obj(y,x))) return;
  458.     cur_pos = popt();
  459.     c_ptr->tptr = cur_pos;
  460.     invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR);
  461.     c_ptr->fval = BLOCKED_FLOOR;
  462.     t_list[cur_pos].p1 = (-randint(10) - 10);
  463. }
  464.  
  465.  
  466. static void 
  467. place_secret_door(y, x)
  468. int y, x;
  469. {
  470.     register int        cur_pos;
  471.     register cave_type *c_ptr;
  472.  
  473.     if (!(c_ptr = test_place_obj(y,x))) return;
  474.     cur_pos = popt();
  475.     c_ptr->tptr = cur_pos;
  476.     invcopy(&t_list[cur_pos], OBJ_SECRET_DOOR);
  477.     c_ptr->fval = BLOCKED_FLOOR;
  478. }
  479.  
  480.  
  481. static void 
  482. place_door(y, x)
  483. int y, x;
  484. {
  485.     register int        tmp;
  486.  
  487.     tmp = randint(8);
  488.     if (tmp < 4) {
  489.     if (randint(4) == 1)
  490.         place_broken_door(y, x);
  491.     else
  492.         place_open_door(y, x);
  493.     } else if (tmp < 7) {
  494.     tmp = randint(100);
  495.     if (tmp > 25)
  496.         place_closed_door(y, x);
  497.     else if (tmp == 3)
  498.         place_stuck_door(y, x);
  499.     else
  500.         place_locked_door(y, x);
  501.     } else
  502.     place_secret_door(y, x);
  503. }
  504.  
  505.  
  506. /* Place an up staircase at given y, x            -RAK-     */
  507. static void 
  508. place_up_stairs(y, x)
  509. int y, x;
  510. {
  511.     register int        cur_pos;
  512.     register cave_type *c_ptr;
  513.  
  514.     if (!(c_ptr = test_place_obj(y,x))) return;
  515.     cur_pos = popt();
  516.     c_ptr->tptr = cur_pos;
  517.     invcopy(&t_list[cur_pos], OBJ_UP_STAIR);
  518.  
  519. }
  520.  
  521.  
  522. /* Place a down staircase at given y, x            -RAK-     */
  523. static void 
  524. place_down_stairs(y, x)
  525. int y, x;
  526. {
  527.     register int        cur_pos;
  528.     register cave_type *c_ptr;
  529.  
  530.     if (is_quest(dun_level)) {
  531.     place_up_stairs(y, x);
  532.     return;
  533.     }
  534.     if (!(c_ptr = test_place_obj(y,x))) return;
  535.     cur_pos = popt();
  536.     c_ptr->tptr = cur_pos;
  537.     invcopy(&t_list[cur_pos], OBJ_DOWN_STAIR);
  538.     if (dun_level == 0)            /* on town level -CWS */
  539.     c_ptr->pl = TRUE;
  540. }
  541.  
  542.  
  543. /* Places a staircase 1=up, 2=down            -RAK-     */
  544. static void 
  545. place_stairs(typ, num, walls)
  546. int typ, num, walls;
  547. {
  548.     register cave_type *cave_ptr;
  549.     int                 i, j, flag;
  550.     register int        y1, x1, y2, x2;
  551.  
  552.     for (i = 0; i < num; i++) {
  553.     flag = FALSE;
  554.     do {
  555.         j = 0;
  556.         do {
  557.         /* Note: don't let y1/x1 be zero, and don't let y2/x2 be equal to
  558.          * cur_height-1/cur_width-1, these values are always
  559.          * BOUNDARY_ROCK. 
  560.          */
  561.         y1 = randint(cur_height - 14);
  562.         x1 = randint(cur_width - 14);
  563.         y2 = y1 + 12;
  564.         x2 = x1 + 12;
  565.         do {
  566.             do {
  567.             cave_ptr = &cave[y1][x1];
  568.             if (cave_ptr->fval <= MAX_OPEN_SPACE
  569.                 && (cave_ptr->tptr == 0)
  570.                 && (next_to_walls(y1, x1) >= walls)) {
  571.                 flag = TRUE;
  572.                 if (typ == 1)
  573.                 place_up_stairs(y1, x1);
  574.                 else
  575.                 place_down_stairs(y1, x1);
  576.             }
  577.             x1++;
  578.             }
  579.             while ((x1 != x2) && (!flag));
  580.             x1 = x2 - 12;
  581.             y1++;
  582.         }
  583.         while ((y1 != y2) && (!flag));
  584.         j++;
  585.         }
  586.         while ((!flag) && (j <= 30));
  587.         walls--;
  588.     }
  589.     while (!flag);
  590.     }
  591. }
  592.  
  593.  
  594. /* Place a trap with a given displacement of point    -RAK-     */
  595. static void 
  596. vault_trap(y, x, yd, xd, num)
  597. int y, x, yd, xd, num;
  598. {
  599.     register int        count, y1, x1;
  600.     int                 i, flag;
  601.     register cave_type *c_ptr;
  602.  
  603.     for (i = 0; i < num; i++) {
  604.     flag = FALSE;
  605.     count = 0;
  606.     do {
  607.         do {           /* add another bounds check -CFT */
  608.         y1 = y - yd - 1 + randint(2 * yd + 1);
  609.         x1 = x - xd - 1 + randint(2 * xd + 1);
  610.         } while (!in_bounds(y1, x1));
  611.         c_ptr = &cave[y1][x1];
  612.         if ((c_ptr->fval != NULL_WALL) && (c_ptr->fval <= MAX_CAVE_FLOOR)
  613.         && (c_ptr->tptr == 0)) {
  614.         place_trap(y1, x1, randint(MAX_TRAP) - 1);
  615.         flag = TRUE;
  616.         }
  617.         count++;
  618.     }
  619.     while ((!flag) && (count <= 5));
  620.     }
  621. }
  622.  
  623.  
  624. /* Place a monster with a given displacement of point    -RAK-     */
  625. static void 
  626. vault_monster(y, x, num)
  627. int y, x, num;
  628. {
  629.     register int i;
  630.     int          y1, x1;
  631.  
  632.     for (i = 0; i < num; i++) {
  633.     y1 = y;
  634.     x1 = x;
  635.     (void)summon_monster(&y1, &x1, TRUE);
  636.     }
  637. }
  638.  
  639. static void 
  640. vault_jelly(y, x)
  641. int y, x;
  642. {
  643.     int l, m, summon;
  644.  
  645.     summon = FALSE;
  646.     l = m_level[MAX_MONS_LEVEL];
  647.     do {
  648.     m = randint(l) - 1;
  649.     if (((c_list[m].cchar == 'j') || (c_list[m].cchar == ',')
  650.          || (c_list[m].cchar == 'i') || (c_list[m].cchar == 'm'))
  651.         && !(c_list[m].cdefense & EVIL)) {
  652.         summon = TRUE;
  653.         place_monster(y, x, m, TRUE);
  654.     }
  655.     } while (!summon);
  656. }
  657.  
  658. static void 
  659. vault_orc(y, x, rank)
  660. int y, x, rank;
  661. {
  662.     register int i;
  663.  
  664.     i = 0;
  665.     switch (rank) {
  666.       case 1:
  667.     while (i < MAX_CREATURES) {
  668.         if (!stricmp(c_list[i].name, "Snaga"))
  669.         break;
  670.         i++;
  671.     }
  672.     break;
  673.       case 2:
  674.       case 3:
  675.     while (i < MAX_CREATURES) {
  676.         if (!stricmp(c_list[i].name, "Black orc"))
  677.         break;
  678.         i++;
  679.     }
  680.     break;
  681.       case 4:
  682.       case 5:
  683.     while (i < MAX_CREATURES) {
  684.         if (!stricmp(c_list[i].name, "Uruk-Hai"))
  685.         break;
  686.         i++;
  687.     }
  688.     break;
  689.       case 6:
  690.     while (i < MAX_CREATURES) {
  691.         if (!stricmp(c_list[i].name, "Orc captain"))
  692.         break;
  693.         i++;
  694.     }
  695.     break;
  696.     }
  697.     if (i != MAX_CREATURES)
  698.     place_monster(y, x, i, FALSE);
  699. }
  700.  
  701. static void 
  702. vault_troll(y, x, rank)
  703. int y, x, rank;
  704. {
  705.     register int i;
  706.  
  707.     i = 0;
  708.     switch (rank) {
  709.       case 1:
  710.     while (i < MAX_CREATURES) {
  711.         if (!stricmp(c_list[i].name, "Forest troll"))
  712.         break;
  713.         i++;
  714.     }
  715.     break;
  716.       case 2:
  717.     while (i < MAX_CREATURES) {
  718.         if (!stricmp(c_list[i].name, "Stone troll"))
  719.         break;
  720.         i++;
  721.     }
  722.     break;
  723.       case 3:
  724.     while (i < MAX_CREATURES) {
  725.         if (!stricmp(c_list[i].name, "Ice troll"))
  726.         break;
  727.         i++;
  728.     }
  729.     break;
  730.       case 4:
  731.     while (i < MAX_CREATURES) {
  732.         if (!stricmp(c_list[i].name, "Cave troll"))
  733.         break;
  734.         i++;
  735.     }
  736.     break;
  737.       case 5:
  738.     while (i < MAX_CREATURES) {
  739.         if (!stricmp(c_list[i].name, "Water troll"))
  740.         break;
  741.         i++;
  742.     }
  743.     break;
  744.       case 6:
  745.     while (i < MAX_CREATURES) {
  746.         if (!stricmp(c_list[i].name, "Olog-Hai"))
  747.         break;
  748.         i++;
  749.     }
  750.     break;
  751.     }
  752.     if (i != MAX_CREATURES)
  753.     place_monster(y, x, i, FALSE);
  754. }
  755.  
  756. static void 
  757. vault_undead(y, x)
  758. int y, x;
  759. {
  760.     int l, m, summon;
  761.     
  762.     summon = FALSE;
  763.     l = m_level[MAX_MONS_LEVEL];
  764.     do {
  765.     m = randint(l) - 1;
  766.     if ((c_list[m].cdefense & UNDEAD) && !(c_list[m].cdefense & UNIQUE)) {
  767.         summon = TRUE;
  768.         place_monster(y, x, m, TRUE);
  769.     }
  770.     } while (!summon);
  771. }
  772.  
  773.  
  774. static void 
  775. vault_dragon(y, x, rank, type)
  776. int y, x, rank, type;
  777. {
  778.     register int i = 0;
  779.  
  780.     switch (rank) {
  781.       case 1:
  782.       case 2:
  783.       case 3:
  784.     switch (type) {
  785.       case 1:
  786.         while (i < MAX_CREATURES) {
  787.         if (!stricmp(c_list[i].name, "Young blue dragon"))
  788.             break;
  789.         i++;
  790.         }
  791.         break;
  792.       case 2:
  793.         while (i < MAX_CREATURES) {
  794.         if (!stricmp(c_list[i].name, "Young white dragon"))
  795.             break;
  796.         i++;
  797.         }
  798.         break;
  799.       case 3:
  800.         while (i < MAX_CREATURES) {
  801.         if (!stricmp(c_list[i].name, "Young green dragon"))
  802.             break;
  803.         i++;
  804.         }
  805.         break;
  806.       case 4:
  807.         while (i < MAX_CREATURES) {
  808.         if (!stricmp(c_list[i].name, "Young black dragon"))
  809.             break;
  810.         i++;
  811.         }
  812.         break;
  813.       case 5:
  814.         while (i < MAX_CREATURES) {
  815.         if (!stricmp(c_list[i].name, "Young red dragon"))
  816.             break;
  817.         i++;
  818.         }
  819.         break;
  820.       case 6:
  821.         while (i < MAX_CREATURES) {
  822.         if (!stricmp(c_list[i].name, "Young Multi-Hued Dragon"))
  823.             break;
  824.         i++;
  825.         }
  826.         break;
  827.     }
  828.     break;
  829.       case 4:
  830.       case 5:
  831.     switch (type) {
  832.       case 1:
  833.         while (i < MAX_CREATURES) {
  834.         if (!stricmp(c_list[i].name, "Mature blue Dragon"))
  835.             break;
  836.         i++;
  837.         }
  838.         break;
  839.       case 2:
  840.         while (i < MAX_CREATURES) {
  841.         if (!stricmp(c_list[i].name, "Mature white Dragon"))
  842.             break;
  843.         i++;
  844.         }
  845.         break;
  846.       case 3:
  847.         while (i < MAX_CREATURES) {
  848.         if (!stricmp(c_list[i].name, "Mature green Dragon"))
  849.             break;
  850.         i++;
  851.         }
  852.         break;
  853.       case 4:
  854.         while (i < MAX_CREATURES) {
  855.         if (!stricmp(c_list[i].name, "Mature black Dragon"))
  856.             break;
  857.         i++;
  858.         }
  859.         break;
  860.       case 5:
  861.         while (i < MAX_CREATURES) {
  862.         if (!stricmp(c_list[i].name, "Mature red Dragon"))
  863.             break;
  864.         i++;
  865.         }
  866.         break;
  867.       case 6:
  868.         while (i < MAX_CREATURES) {
  869.         if (!stricmp(c_list[i].name, "Mature Multi-Hued Dragon"))
  870.             break;
  871.         i++;
  872.         }
  873.         break;
  874.     }
  875.     break;
  876.       case 6:
  877.     switch (type) {
  878.       case 1:
  879.         while (i < MAX_CREATURES) {
  880.         if (!stricmp(c_list[i].name, "Ancient blue Dragon"))
  881.             break;
  882.         i++;
  883.         }
  884.         break;
  885.       case 2:
  886.         while (i < MAX_CREATURES) {
  887.         if (!stricmp(c_list[i].name, "Ancient white Dragon"))
  888.             break;
  889.         i++;
  890.         }
  891.         break;
  892.       case 3:
  893.         while (i < MAX_CREATURES) {
  894.         if (!stricmp(c_list[i].name, "Ancient green Dragon"))
  895.             break;
  896.         i++;
  897.         }
  898.         break;
  899.       case 4:
  900.         while (i < MAX_CREATURES) {
  901.         if (!stricmp(c_list[i].name, "Ancient black Dragon"))
  902.             break;
  903.         i++;
  904.         }
  905.         break;
  906.       case 5:
  907.         while (i < MAX_CREATURES) {
  908.         if (!stricmp(c_list[i].name, "Ancient red Dragon"))
  909.             break;
  910.         i++;
  911.         }
  912.         break;
  913.       case 6:
  914.         while (i < MAX_CREATURES) {
  915.         if (!stricmp(c_list[i].name, "Ancient Multi-Hued Dragon"))
  916.             break;
  917.         i++;
  918.         }
  919.         break;
  920.     }
  921.     break;
  922.     }
  923.     if (i != MAX_CREATURES)
  924.     place_monster(y, x, i, FALSE);
  925. }
  926.  
  927. static void 
  928. vault_demon(y, x, rank)
  929. int y, x, rank;
  930. {
  931.     register int i = 0;
  932.  
  933.     switch (rank) {
  934.       case 1:
  935.     while (i < MAX_CREATURES) {
  936.         if (!stricmp(c_list[i].name, "Vrock"))
  937.         break;
  938.         i++;
  939.     }
  940.     break;
  941.       case 2:
  942.     while (i < MAX_CREATURES) {
  943.         if (!stricmp(c_list[i].name, "Hezrou"))
  944.         break;
  945.         i++;
  946.     }
  947.     break;
  948.       case 3:
  949.     while (i < MAX_CREATURES) {
  950.         if (!stricmp(c_list[i].name, "Glabrezu"))
  951.         break;
  952.         i++;
  953.     }
  954.     break;
  955.       case 4:
  956.     while (i < MAX_CREATURES) {
  957.         if (!stricmp(c_list[i].name, "Nalfeshnee"))
  958.         break;
  959.         i++;
  960.     }
  961.     break;
  962.       case 5:
  963.     while (i < MAX_CREATURES) {
  964.         if (!stricmp(c_list[i].name, "Marilith"))
  965.         break;
  966.         i++;
  967.     }
  968.     break;
  969.       case 6:
  970.     while (i < MAX_CREATURES) {
  971.         if (!stricmp(c_list[i].name, "Lesser balrog"))
  972.         break;
  973.         i++;
  974.     }
  975.     break;
  976.     }
  977.     if (i != MAX_CREATURES)
  978.     place_monster(y, x, i, FALSE);
  979. }
  980.  
  981.  
  982. static void 
  983. vault_giant(y, x, rank)
  984. int y, x, rank;
  985. {
  986.     register int i = 0;
  987.  
  988.     switch (rank) {
  989.       case 1:
  990.     while (i < MAX_CREATURES) {
  991.         if (!stricmp(c_list[i].name, "Hill giant"))
  992.         break;
  993.         i++;
  994.     }
  995.     break;
  996.       case 2:
  997.     while (i < MAX_CREATURES) {
  998.         if (!stricmp(c_list[i].name, "Frost giant"))
  999.         break;
  1000.         i++;
  1001.     }
  1002.     break;
  1003.       case 3:
  1004.     while (i < MAX_CREATURES) {
  1005.         if (!stricmp(c_list[i].name, "Fire giant"))
  1006.         break;
  1007.         i++;
  1008.     }
  1009.     break;
  1010.       case 4:
  1011.     while (i < MAX_CREATURES) {
  1012.         if (!stricmp(c_list[i].name, "Stone giant"))
  1013.         break;
  1014.         i++;
  1015.     }
  1016.     break;
  1017.       case 5:
  1018.     while (i < MAX_CREATURES) {
  1019.         if (!stricmp(c_list[i].name, "Cloud giant"))
  1020.         break;
  1021.         i++;
  1022.     }
  1023.     break;
  1024.       case 6:
  1025.     while (i < MAX_CREATURES) {
  1026.         if (!stricmp(c_list[i].name, "Storm giant"))
  1027.         break;
  1028.         i++;
  1029.     }
  1030.     break;
  1031.     }
  1032.     if (i != MAX_CREATURES)
  1033.     place_monster(y, x, i, FALSE);
  1034. }
  1035.  
  1036.  
  1037. /* Builds a room at a row, column coordinate        -RAK-     */
  1038. static void 
  1039. build_room(yval, xval)
  1040. int yval, xval;
  1041. {
  1042.     register int        i, j, y_depth, x_right;
  1043.     int                 y_height, x_left;
  1044.     int8u               floor;
  1045.     register cave_type *c_ptr, *d_ptr;
  1046.  
  1047.     if (dun_level <= randint(25))
  1048.     floor = LIGHT_FLOOR;       /* Floor with light     */
  1049.     else
  1050.     floor = DARK_FLOOR;       /* Dark floor         */
  1051.  
  1052.     y_height = yval - randint(4);
  1053.     y_depth = yval + randint(3);
  1054.     x_left = xval - randint(11);
  1055.     x_right = xval + randint(11);
  1056.  
  1057. /* for paranoia's sake: bounds-check!  Memory errors caused by accessing
  1058.  * cave[][] out-of-bounds are nearly impossible to spot!  -CFT 
  1059.  */
  1060.     if (y_height < 1)
  1061.     y_height = 1;
  1062.     if (y_depth >= (cur_height - 1))
  1063.     y_depth = cur_height - 2;
  1064.     if (x_left < 1)
  1065.     x_left = 1;
  1066.     if (x_right >= (cur_width - 1))
  1067.     x_right = cur_width - 2;
  1068.  
  1069. /* the x dim of rooms tends to be much larger than the y dim, so don't bother
  1070.  * rewriting the y loop 
  1071.  */
  1072.     for (i = y_height; i <= y_depth; i++) {
  1073.     c_ptr = &cave[i][x_left];
  1074.     for (j = x_left; j <= x_right; j++) {
  1075.         c_ptr->fval = floor;
  1076.         c_ptr->lr = TRUE;
  1077.         c_ptr++;
  1078.     }
  1079.     }
  1080.  
  1081.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  1082.     c_ptr = &cave[i][x_left - 1];
  1083.     c_ptr->fval = GRANITE_WALL;
  1084.     c_ptr->lr = TRUE;
  1085.     c_ptr = &cave[i][x_right + 1];
  1086.     c_ptr->fval = GRANITE_WALL;
  1087.     c_ptr->lr = TRUE;
  1088.     }
  1089.  
  1090.     c_ptr = &cave[y_height - 1][x_left];
  1091.     d_ptr = &cave[y_depth + 1][x_left];
  1092.     for (i = x_left; i <= x_right; i++) {
  1093.     c_ptr->fval = GRANITE_WALL;
  1094.     c_ptr->lr = TRUE;
  1095.     c_ptr++;
  1096.     d_ptr->fval = GRANITE_WALL;
  1097.     d_ptr->lr = TRUE;
  1098.     d_ptr++;
  1099.     }
  1100.  
  1101. /* Every so often fill a normal room with pillars - Decado */
  1102.  
  1103.     if (randint(20) == 2) {
  1104.     for (i = y_height; i <= y_depth; i += 2) {
  1105.         for (j = x_left; j <= x_right; j += 2) {
  1106.         c_ptr = &cave[i][j];
  1107.         c_ptr->fval = TMP1_WALL;
  1108.         c_ptr->lr = TRUE;
  1109.         }
  1110.     }
  1111.     }
  1112. }
  1113.  
  1114. /* Builds a room at a row, column coordinate        -RAK-     */
  1115. /* Type 1 unusual rooms are several overlapping rectangular ones     */
  1116. static void 
  1117. build_type1(yval, xval)
  1118. int yval, xval;
  1119. {
  1120.     int                 y_height, y_depth;
  1121.     int                 x_left, x_right, limit;
  1122.     register int        i0, i, j;
  1123.     int8u               floor;
  1124.     register cave_type *c_ptr, *d_ptr;
  1125.  
  1126.     if (dun_level <= randint(25))
  1127.     floor = LIGHT_FLOOR;       /* Floor with light     */
  1128.     else
  1129.     floor = DARK_FLOOR;       /* Dark floor         */
  1130.     limit = 1 + randint(2);
  1131.     for (i0 = 0; i0 < limit; i0++) {
  1132.     y_height = yval - randint(4);
  1133.     y_depth = yval + randint(3);
  1134.     x_left = xval - randint(11);
  1135.     x_right = xval + randint(11);
  1136.  
  1137.     /* for paranoia's sake: bounds-check!  Memory errors caused by accessing
  1138.      * cave[][] out-of-bounds are nearly impossible to spot!  -CFT 
  1139.      */
  1140.     if (y_height < 1)
  1141.         y_height = 1;
  1142.     if (y_depth >= (cur_height - 1))
  1143.         y_depth = cur_height - 2;
  1144.     if (x_left < 1)
  1145.         x_left = 1;
  1146.     if (x_right >= (cur_width - 1))
  1147.         x_right = cur_width - 2;
  1148.  
  1149.     /* the x dim of rooms tends to be much larger than the y dim, so don't
  1150.      * bother rewriting the y loop 
  1151.      */
  1152.  
  1153.     for (i = y_height; i <= y_depth; i++) {
  1154.         c_ptr = &cave[i][x_left];
  1155.         for (j = x_left; j <= x_right; j++) {
  1156.         c_ptr->fval = floor;
  1157.         c_ptr->lr = TRUE;
  1158.         c_ptr++;
  1159.         }
  1160.     }
  1161.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  1162.         c_ptr = &cave[i][x_left - 1];
  1163.         if (c_ptr->fval != floor) {
  1164.         c_ptr->fval = GRANITE_WALL;
  1165.         c_ptr->lr = TRUE;
  1166.         }
  1167.         c_ptr = &cave[i][x_right + 1];
  1168.         if (c_ptr->fval != floor) {
  1169.         c_ptr->fval = GRANITE_WALL;
  1170.         c_ptr->lr = TRUE;
  1171.         }
  1172.     }
  1173.     c_ptr = &cave[y_height - 1][x_left];
  1174.     d_ptr = &cave[y_depth + 1][x_left];
  1175.     for (i = x_left; i <= x_right; i++) {
  1176.         if (c_ptr->fval != floor) {
  1177.         c_ptr->fval = GRANITE_WALL;
  1178.         c_ptr->lr = TRUE;
  1179.         }
  1180.         c_ptr++;
  1181.         if (d_ptr->fval != floor) {
  1182.         d_ptr->fval = GRANITE_WALL;
  1183.         d_ptr->lr = TRUE;
  1184.         }
  1185.         d_ptr++;
  1186.     }
  1187.     }
  1188. }
  1189.  
  1190. /* Wish me LUCK! - Decado */
  1191.  
  1192. static void 
  1193. build_type5(yval, xval)
  1194. int yval, xval;
  1195. {
  1196.     register int        x, y, x1, y1, vault;
  1197.     int                 width = 0, height = 0;
  1198.     char               *template = NULL;
  1199. /* use t to avoid changing template in loop.  This should fix some memory
  1200.  * troubles, because now we aren't free()ing with a bad pointer.  Thanks
  1201.  * much to gehring@pib1.physik.uni-bonn.edu for pointing this bug out... -CFT
  1202.  */
  1203.     char               *t;
  1204.     char                buf[50];
  1205.     int8u               floor;
  1206.     int8u               wall;
  1207.     register cave_type *c_ptr;
  1208.  
  1209.     if (dun_level <= randint(25))
  1210.     floor = LIGHT_FLOOR;       /* Floor with light */
  1211.     else
  1212.     floor = DARK_FLOOR;       /* Dark floor       */
  1213.  
  1214.  
  1215.     vault = 0;
  1216.     switch (randint(8)) {
  1217.       case 1:
  1218.     width = 20;
  1219.     height = 12;
  1220.     template = (char *)malloc((size_t) width * height + 1);
  1221.     rating += 5;
  1222.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1223.         "       %%%%%%       ",
  1224.         "    %%%..##..%%%    ",
  1225.         "  %%....####....%%  ",
  1226.         " %......#**#......% ",
  1227.         "%...,.##+##+##.,...%",
  1228.         "%.,.,.#*#*&#*#.,.,.%",
  1229.         "%.,.,.#*#&*#*#.,.,.%",
  1230.         "%...,.##+##+##.,...%",
  1231.         " %......#**#......% ",
  1232.         "  %%....####....%%  ",
  1233.         "    %%%..##..%%%    ",
  1234.         "       %%%%%%       ");
  1235.     break;
  1236.       case 2:
  1237.     width = 20;
  1238.     height = 14;
  1239.     template = (char *)malloc((size_t) width * height + 1);
  1240.     rating += 5;
  1241.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1242.         "   %%%%%%%%%%%%%%   ",
  1243.         "  %%.##########.%%  ",
  1244.         " %%..#..,,,,..#..%% ",
  1245.         "%%,..#.,####,.#..,%%",
  1246.         "%....#.,#**#,.#....%",
  1247.         "%.###+,##&&##,+###.%",
  1248.         "%.#..,,#*&**#,,..#.%",
  1249.         "%.#..,,#**&*#,,..#.%",
  1250.         "%.###+,##&&##,+###.%",
  1251.         "%....#.,#**#,.#....%",
  1252.         "%%,..#.,####,.#..,%%",
  1253.         " %%..#..,,,,..#..%% ",
  1254.         "  %%.##########.%%  ",
  1255.         "   %%%%%%%%%%%%%%   ");
  1256.     break;
  1257.       case 3:
  1258.     width = 20;
  1259.     height = 12;
  1260.     template = (char *)malloc((size_t) width * height + 1);
  1261.     rating += 5;
  1262.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1263.         "    %%%%%%%%%%%%    ",
  1264.         " %%%%..........%%%% ",
  1265.         " %...###+##+###...% ",
  1266.         "%%...#,,#,,#,,#...%%",
  1267.         "%.###+##+##+##+###.%",
  1268.         "%.#,,#&&#**#&&#,,#.%",
  1269.         "%.#,,#&&#**#&&#,,#.%",
  1270.         "%.###+##+##+##+###.%",
  1271.         "%%...#,,#,,#,,#...%%",
  1272.         " %...###+##+###...% ",
  1273.         " %%%%..........%%%% ",
  1274.         "    %%%%%%%%%%%%    ");
  1275.     break;
  1276.       case 4:
  1277.     width = 20;
  1278.     height = 12;
  1279.     template = (char *)malloc((size_t) width * height + 1);
  1280.     rating += 5;
  1281.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1282.         "%%%%%%%%%%%%%%%%%%%%",
  1283.         "%*.......&........*%",
  1284.         "%.################.%",
  1285.         "%.#,.,.,.,.,.,.,.#.%",
  1286.         "%.#.############,#.%",
  1287.         "%.#,+,&&+**#&*,#.#&%",
  1288.         "%&#.#,*&#**+&&,+,#.%",
  1289.         "%.#,############.#.%",
  1290.         "%.#.,.,.,.,.,.,.,#.%",
  1291.         "%.################.%",
  1292.         "%*........&.......*%",
  1293.         "%%%%%%%%%%%%%%%%%%%%");
  1294.     break;
  1295.       case 5:
  1296.     width = 20;
  1297.     height = 12;
  1298.     template = (char *)malloc((size_t) width * height + 1);
  1299.     rating += 5;
  1300.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1301.         "%%%%%%%%%%%%%%%%%   ",
  1302.         "%,,,##,,,,##....%%  ",
  1303.         "%,,,,##,,,,##....%% ",
  1304.         "%#,,,,##,,,,##....%%",
  1305.         "%##,,,,##,,,,##....%",
  1306.         "%.##,,,,,,,,,,#+...%",
  1307.         "%..#+,,,,,,,,,,##..%",
  1308.         "%...##,,,,##,,,,##.%",
  1309.         "%%...##,,,,##,,,,##%",
  1310.         " %%...##,,,,##,,,,#%",
  1311.         "  %%...##,,,,##,,,,%",
  1312.         "   %%%%%%%%%%%%%%%%%");
  1313.     break;
  1314.       case 6:
  1315.     width = 20;
  1316.     height = 12;
  1317.     template = (char *)malloc((size_t) width * height + 1);
  1318.     rating += 5;
  1319.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1320.         "   %%%%%%%%%%%%%%%%%",
  1321.         "  %%....##,,,,##,,,%",
  1322.         " %%....##,,,,##,,,,%",
  1323.         "%%....##,,,,##,,,,#%",
  1324.         "%....##,,,,##,,,,##%",
  1325.         "%...+#,,,,,,,,,,##.%",
  1326.         "%..##,,,,,,,,,,+#..%",
  1327.         "%.##,,,,##,,,,##...%",
  1328.         "%##,,,,##,,,,##...%%",
  1329.         "%#,,,,##,,,,##...%% ",
  1330.         "%,,,,##,,,,##...%%  ",
  1331.         "%%%%%%%%%%%%%%%%%   ");
  1332.     break;
  1333.       case 7:
  1334.     width = 20;
  1335.     height = 12;
  1336.     template = (char *)malloc((size_t) width * height + 1);
  1337.     rating += 5;
  1338.     sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1339.         "%%%%%%%%%%%%%%%%%%%%",
  1340.         "%,################,%",
  1341.         "%^#.*...&..,....,#^%",
  1342.         "%^#...,......&...#^%",
  1343.         "%^#######++#######^%",
  1344.         "%^+.,..&+,*+*....+^%",
  1345.         "%^+..*.,+.&+.,.&.+^%",
  1346.         "%^#######++#######^%",
  1347.         "%^#....,.,.....,.#^%",
  1348.         "%^#..&......*....#^%",
  1349.         "%,################,%",
  1350.         "%%%%%%%%%%%%%%%%%%%%");
  1351.     break;
  1352.       case 8:
  1353.     vault = TRUE;
  1354.     switch (randint(4)) {
  1355.       case 4:
  1356.         width = 40;
  1357.         height = 18;
  1358.         template = (char *)malloc((size_t) width * height + 1);
  1359.         rating += 25;
  1360.         sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1361.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
  1362.             "%######################################%",
  1363.             "%#*8..&##***++^^^^^^^^^^^^++***##&..*8#%",
  1364.             "%#8..&##,,,,,##^^^^^^^^^^##,,,,,X#&..*#%",
  1365.             "%#..&X#.....,.##^^^^^^^^##..&....##&..#%",
  1366.             "%#.&##..,.&....##^^^^^^##..,...&..##&.#%",
  1367.             "%#&##..*...&.^..##^^^^##..*....,..,##&#%",
  1368.             "%####+#############++#############+####%",
  1369.             "%+....,.,.#&&&&***+88+***&&&&#,.,.,...+%",
  1370.             "%+...,.,.,#&&&&***+88+***&&&&#.,.,....+%",
  1371.             "%####+#############++#############+####%",
  1372.             "%#&##..*....&...##^^^^##...*...&,..X#&#%",
  1373.             "%#.&##..&.^....##^^^^^^##....&....##&.#%",
  1374.             "%#..&##....&..##^^^^^^^^##..,..*.##&..#%",
  1375.             "%#*..&X#,,,,,##^^^^^^^^^^##,,,,,##&..8#%",
  1376.             "%#8*..&##***++^^^^^^^^^^^^++***##&..*8#%",
  1377.             "%######################################%",
  1378.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  1379.         break;
  1380.       case 3:
  1381.         width = 39;
  1382.         height = 17;
  1383.         template = (char *)malloc((size_t) width * height + 1);
  1384.         rating += 35;
  1385.         sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1386.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
  1387.             "%#####################################%",
  1388.             "%+&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XO#%",
  1389.             "%###################################X#%",
  1390.             "%#OX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&#%",
  1391.             "%#X###################################%",
  1392.             "%#&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XO#%",
  1393.             "%###################################X#%",
  1394.             "%#OX&XOX&XOX&XOOOOOOOOOOOXOX&XOX&XOX&#%",
  1395.             "%#X###################################%",
  1396.             "%#&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XO#%",
  1397.             "%###################################X#%",
  1398.             "%#OX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&#%",
  1399.             "%#X###################################%",
  1400.             "%#&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&X&+%",
  1401.             "%#####################################%",
  1402.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  1403.         break;
  1404.       case 2:
  1405.         width = 40;
  1406.         height = 18;
  1407.         template = (char *)malloc((size_t) width * height + 1);
  1408.         rating += 30;
  1409.         sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1410.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
  1411.             "%######################################%",
  1412.             "%#,X,X,X,X,X,X,X,X*@@*X,X,X,X,X,X,X,X,#%",
  1413.             "%#+################XX################+#%",
  1414.             "%#.,..,.#&.&.,*##******##*,.&.&#.,...,X%",
  1415.             "%#..,.^^#....,##***@@***##,....#^^..,.X%",
  1416.             "%######+#^&.&##***@XX@***##&.&^#+######%",
  1417.             "%#,.&.^^#+####***@X##X@***####+#^^.,..#%",
  1418.             "%#..,&,.#^^^@#**@X#OO#X@**X@^^^#.,..&,#%",
  1419.             "%#.,....#^^^@X**@X#OO#X@**#@^^^#.&.,..#%",
  1420.             "%#...,^^#+####***@X##X@***####+#^^..,.#%",
  1421.             "%######+#^&.&##***@XX@***##&.&^#+######%",
  1422.             "%X.,..^^#.....##***@@***##,....#^^.,..#%",
  1423.             "%X...,..#&.&.,*##******##*,.&.&#..,..,#%",
  1424.             "%#+################XX################+#%",
  1425.             "%#,X,X,X,X,X,X,X,X*@@*X,X,X,X,X,X,X,X,#%",
  1426.             "%######################################%",
  1427.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  1428.         break;
  1429.       case 1:
  1430.         width = 40;
  1431.         height = 15;
  1432.         template = (char *)malloc((size_t)width * height + 1);
  1433.         rating += 25;
  1434.         sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1435.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
  1436.             "%&+.^..^..^..^..^..^..^..^..^..^..^..+&%",
  1437.             "%+####################################+%",
  1438.             "%.#.&.^,#&^&^#****+^*^@^#.*.&..#..*.,#.%",
  1439.             "%^#.,.&^+^&^@#^^^^#@^*^*#....*^+.^...#^%",
  1440.             "%.#*..,.###+####+####+###.&.^..#..&,.#.%",
  1441.             "%^#..^.*#*..^&&@@*#,,,,,####+###,....#^%",
  1442.             "%.##+##############,*O*,#,,,,,,###+###.%",
  1443.             "%^#*&#.&,*.#,*&^*^#,,,,,#,,,,,,#....,#^%",
  1444.             "%.#&,+....*+,*&^*^##########+###.,...+.%",
  1445.             "%^#.,#.*.&.#,*&^*^+.,.&.^*.&^&^#.....#^%",
  1446.             "%.#^*#.,..,#,*&^*^#*.^*.,..&&&^#,..,.#.%",
  1447.             "%+####################################+%",
  1448.             "%&+..^..^..^..^..^..^..^..^..^..^..^.+&%",
  1449.             "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  1450.         break;
  1451.     }
  1452.     break;
  1453.     }
  1454.  
  1455. /* check these rooms will fit on the map! */
  1456.  
  1457.     wall = TMP1_WALL;
  1458.     if (vault) {
  1459.     xval += 4;           /* neat kludge deccy... */
  1460.     yval += 4;
  1461.     wall = BOUNDARY_WALL;
  1462.     if (floor == LIGHT_FLOOR)
  1463.         floor = NT_LIGHT_FLOOR;
  1464.     else
  1465.         floor = NT_DARK_FLOOR;
  1466.     }
  1467. /* DO NOT CHANGE yval or xval after this check... */
  1468.     if (!(in_bounds(yval - (height / 2), xval - (width / 2)) &&
  1469.       in_bounds(yval + (height / 2), xval + (width / 2)))) {
  1470.     free(template);
  1471.     build_type2(yval, xval);
  1472.     return;
  1473.     }
  1474.  
  1475.     if ((dun_level <= 40) ||
  1476.     (randint((dun_level - 30)*(dun_level - 30) + 1) < 400))
  1477.     good_item_flag = TRUE;     /* this is more like it.... -CWS */
  1478.  
  1479.     t = template;        /* this avoids memory troubles... see above -CFT */
  1480.     for (y = 0; y < height; y++) {
  1481.     for (x = 0; x < width; x++) {
  1482.         x1 = xval - (width / 2) + x;
  1483.         y1 = yval - (height / 2) + y;
  1484.         c_ptr = &cave[y1][x1];
  1485.         switch (*t++) {
  1486.           case '#':       /* lit up wall */
  1487.         c_ptr->fval = wall;
  1488.         c_ptr->lr = TRUE;
  1489.         break;
  1490.           case 'X':
  1491.         c_ptr->fval = TMP1_WALL;
  1492.         c_ptr->lr = TRUE;
  1493.         break;
  1494.           case '%':       /* lit up wall */
  1495.         c_ptr->fval = GRANITE_WALL; /* Not temp, since this may have doors in */
  1496.         c_ptr->lr = TRUE;
  1497.         break;
  1498.           case '.':       /* lit up/ not lit up floor */
  1499.         c_ptr->fval = floor;
  1500.         c_ptr->lr = TRUE;
  1501.         break;
  1502.           case '*':       /* treasure/trap */
  1503.         c_ptr->fval = floor;
  1504.         if (randint(20) > 7) {
  1505.             object_level = dun_level;
  1506.             place_object(y1, x1);
  1507.         }
  1508.         else if (randint(10) > 2)
  1509.             place_trap(y1, x1, randint(MAX_TRAP) - 1);
  1510.         else if (randint(2) == 1 && !vault)
  1511.             place_down_stairs(y1, x1);
  1512.         else if (!vault)
  1513.             place_up_stairs(y1, x1);
  1514.         c_ptr->lr = TRUE;
  1515.         break;
  1516.           case '+':       /* secret doors */
  1517.         place_secret_door(y1, x1);
  1518.         c_ptr->lr = TRUE;
  1519.         break;
  1520.           case '^':
  1521.         c_ptr->fval = floor;
  1522.         place_trap(y1, x1, randint(MAX_TRAP) - 1);
  1523.         c_ptr->lr = TRUE;
  1524.         break;
  1525.           case ' ':
  1526.         break;
  1527.           case '&': case '@': case '8': case 'O': case ',':
  1528.         /* do nothing for now... cannot place monster until whole
  1529.          * area is built, OW group monsters screw things up by being
  1530.          * placed where walls will be placed on top of them  -CFT
  1531.          */
  1532.         break;
  1533.           default:
  1534. #if 0
  1535.         sprintf(buf, "Cockup='%c'", *t);
  1536.         msg_print(buf);
  1537. #endif
  1538.         break;
  1539.         }
  1540.     }
  1541.     }
  1542.     /* now we go back and place the monsters, hopefully this makes
  1543.      * everything happy... -CFT */
  1544.     t = template; /* this avoids memory troubles... see above -CFT */
  1545.     for (y=0; y<height; y++) {
  1546.     for (x=0; x<width; x++) {
  1547.         x1=xval-(width/2)+x;
  1548.         y1=yval-(height/2)+y;
  1549.         c_ptr = &cave[y1][x1];
  1550.         switch (*t++) {
  1551.           case '#': case 'X': case '%': case '*':
  1552.           case '+': case '^': case '.':
  1553.         /* we already placed all of these... -CFT */
  1554.         break;
  1555.  
  1556.           case '&':       /* Monster */
  1557.         c_ptr->fval = floor;
  1558.         place_monster(y1, x1,
  1559.         get_mons_num(dun_level + MON_SUMMON_ADJ + 2 + vault), TRUE);
  1560.         c_ptr->lr = TRUE;
  1561.         break;
  1562.           case '@':       /* Meaner monster */
  1563.         c_ptr->fval = floor;
  1564.         place_monster(y1, x1,
  1565.                   get_nmons_num(dun_level + MON_SUMMON_ADJ + 7),
  1566.                   TRUE);
  1567.         c_ptr->lr = TRUE;
  1568.         break;
  1569.           case '8':       /* Meaner monster */
  1570.         c_ptr->fval = floor;
  1571.         place_monster(y1, x1,
  1572.                   get_nmons_num(dun_level + MON_SUMMON_ADJ + 7),
  1573.                   TRUE);
  1574.         place_special(y1, x1, 1);
  1575.         c_ptr->lr = TRUE;
  1576.         break;
  1577.           case 'O':       /* Nasty monster and treasure */
  1578.         c_ptr->fval = floor;
  1579.         place_monster(y1, x1,
  1580.                   get_nmons_num(dun_level + MON_SUMMON_ADJ + 40),
  1581.                   TRUE);
  1582.         object_level = dun_level + MON_SUMMON_ADJ + 20;
  1583.         place_special(y1, x1, SPECIAL);
  1584.         object_level = dun_level + 7;
  1585.         c_ptr->lr = TRUE;
  1586.         break;
  1587.           case ',':       /* Monster/object */
  1588.         c_ptr->fval = floor;
  1589.         if (randint(2) == 1)
  1590.             place_monster(y1, x1,
  1591.             get_mons_num(dun_level + MON_SUMMON_ADJ + vault), TRUE);
  1592.         if (randint(2) == 1) {
  1593.             object_level = dun_level + 7;
  1594.             place_object(y1, x1);
  1595.         }
  1596.         c_ptr->lr = TRUE;
  1597.         break;
  1598.           case ' ':
  1599.         break;
  1600.           default:
  1601. #if 0
  1602.         sprintf(buf, "Cockup='%c'", *t);
  1603.         msg_print(buf);
  1604. #endif
  1605.         break;
  1606.         }
  1607.     }
  1608.     }
  1609.     free(template);
  1610. }
  1611.  
  1612. /* Builds an unusual room at a row, column coordinate    -RAK-
  1613.  *
  1614.  * Type 2 unusual rooms all have an inner room:
  1615.  * 1 - Just an inner room with one door
  1616.  * 2 - An inner room within an inner room
  1617.  * 3 - An inner room with pillar(s)
  1618.  * 4 - Inner room has a maze
  1619.  * 5 - A set of four inner rooms
  1620.  */
  1621.  
  1622. static void 
  1623. build_type2(yval, xval)
  1624. int yval, xval;
  1625. {
  1626.     register int        i, j, y_height, x_left;
  1627.     int                 y_depth, x_right, tmp;
  1628.     int8u               floor;
  1629.     register cave_type *c_ptr, *d_ptr;
  1630.  
  1631.     if (dun_level <= randint(25))
  1632.     floor = LIGHT_FLOOR;       /* Floor with light     */
  1633.     else
  1634.     floor = DARK_FLOOR;       /* Dark floor         */
  1635.     y_height = yval - 4;
  1636.     y_depth = yval + 4;
  1637.     x_left = xval - 11;
  1638.     x_right = xval + 11;
  1639.  
  1640. /* paranoia bounds-check...   if the room can't fit in the cave, punt out and
  1641.  * build a simpler room type (type1 is already bounds-checked) This should
  1642.  * help solve MORE memory troubles! -CFT 
  1643.  */
  1644.     if (!in_bounds(y_height, x_left) || !in_bounds(y_depth, x_right)) {
  1645.     build_type1(yval, xval);
  1646.     return;
  1647.     }
  1648.  
  1649. /* the x dim of rooms tends to be much larger than the y dim, so don't bother
  1650.  * rewriting the y loop 
  1651.  */
  1652.  
  1653.     for (i = y_height; i <= y_depth; i++) {
  1654.     c_ptr = &cave[i][x_left];
  1655.     for (j = x_left; j <= x_right; j++) {
  1656.         c_ptr->fval = floor;
  1657.         c_ptr->lr = TRUE;
  1658.         c_ptr++;
  1659.     }
  1660.     }
  1661.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  1662.     c_ptr = &cave[i][x_left - 1];
  1663.     c_ptr->fval = GRANITE_WALL;
  1664.     c_ptr->lr = TRUE;
  1665.     c_ptr = &cave[i][x_right + 1];
  1666.     c_ptr->fval = GRANITE_WALL;
  1667.     c_ptr->lr = TRUE;
  1668.     }
  1669.     c_ptr = &cave[y_height - 1][x_left];
  1670.     d_ptr = &cave[y_depth + 1][x_left];
  1671.     for (i = x_left; i <= x_right; i++) {
  1672.     c_ptr->fval = GRANITE_WALL;
  1673.     c_ptr->lr = TRUE;
  1674.     c_ptr++;
  1675.     d_ptr->fval = GRANITE_WALL;
  1676.     d_ptr->lr = TRUE;
  1677.     d_ptr++;
  1678.     }
  1679. /* The inner room         */
  1680.     y_height = y_height + 2;
  1681.     y_depth = y_depth - 2;
  1682.     x_left = x_left + 2;
  1683.     x_right = x_right - 2;
  1684.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  1685.     cave[i][x_left - 1].fval = TMP1_WALL;
  1686.     cave[i][x_right + 1].fval = TMP1_WALL;
  1687.     }
  1688.     c_ptr = &cave[y_height - 1][x_left];
  1689.     d_ptr = &cave[y_depth + 1][x_left];
  1690.     for (i = x_left; i <= x_right; i++) {
  1691.     c_ptr->fval = TMP1_WALL;
  1692.     c_ptr++;
  1693.     d_ptr->fval = TMP1_WALL;
  1694.     d_ptr++;
  1695.     }
  1696. /* Inner room variations         */
  1697.     switch (randint(5)) {
  1698.       case 1:               /* Just an inner room.     */
  1699.     tmp = randint(4);
  1700.     if (tmp < 3) {           /* Place a door     */
  1701.         if (tmp == 1)
  1702.         place_secret_door(y_height - 1, xval);
  1703.         else
  1704.         place_secret_door(y_depth + 1, xval);
  1705.     } else {
  1706.         if (tmp == 3)
  1707.         place_secret_door(yval, x_left - 1);
  1708.         else
  1709.         place_secret_door(yval, x_right + 1);
  1710.     }
  1711.     vault_monster(yval, xval, 1);
  1712.     break;
  1713.  
  1714.       case 2:               /* Treasure Vault     */
  1715.     tmp = randint(4);
  1716.     if (tmp < 3) {           /* Place a door     */
  1717.         if (tmp == 1)
  1718.         place_secret_door(y_height - 1, xval);
  1719.         else
  1720.         place_secret_door(y_depth + 1, xval);
  1721.     } else {
  1722.         if (tmp == 3)
  1723.         place_secret_door(yval, x_left - 1);
  1724.         else
  1725.         place_secret_door(yval, x_right + 1);
  1726.     }
  1727.  
  1728.     for (i = yval - 1; i <= yval + 1; i++) {
  1729.         cave[i][xval - 1].fval = TMP1_WALL;
  1730.         cave[i][xval + 1].fval = TMP1_WALL;
  1731.     }
  1732.     cave[yval - 1][xval].fval = TMP1_WALL;
  1733.     cave[yval + 1][xval].fval = TMP1_WALL;
  1734.  
  1735.     tmp = randint(4);       /* Place a door     */
  1736.     if (tmp < 3)
  1737.         place_locked_door(yval - 3 + (tmp << 1), xval); /* 1 -> yval-1; 2 -> yval+1 */
  1738.     else
  1739.         place_locked_door(yval, xval - 7 + (tmp << 1));
  1740.  
  1741.     /* Place an object in the treasure vault     */
  1742.     tmp = randint(10);
  1743.     if (tmp > 2) {
  1744.         object_level = dun_level;
  1745.         place_object(yval, xval);
  1746.     }
  1747.     else if (tmp == 2)
  1748.         place_down_stairs(yval, xval);
  1749.     else
  1750.         place_up_stairs(yval, xval);
  1751.  
  1752.     /* Guard the treasure well         */
  1753.     vault_monster(yval, xval, 2 + randint(3));
  1754.     /* If the monsters don't get 'em.     */
  1755.     vault_trap(yval, xval, 4, 10, 2 + randint(3));
  1756.     break;
  1757.  
  1758.       case 3:               /* Inner pillar(s).     */
  1759.     tmp = randint(4);
  1760.     if (tmp < 3) {           /* Place a door     */
  1761.         if (tmp == 1)
  1762.         place_secret_door(y_height - 1, xval);
  1763.         else
  1764.         place_secret_door(y_depth + 1, xval);
  1765.     } else {
  1766.         if (tmp == 3)
  1767.         place_secret_door(yval, x_left - 1);
  1768.         else
  1769.         place_secret_door(yval, x_right + 1);
  1770.     }
  1771.  
  1772.     for (i = yval - 1; i <= yval + 1; i++) {
  1773.         c_ptr = &cave[i][xval - 1];
  1774.         for (j = xval - 1; j <= xval + 1; j++) {
  1775.         c_ptr->fval = TMP1_WALL;
  1776.         c_ptr++;
  1777.         }
  1778.     }
  1779.     if (randint(2) == 1) {
  1780.         tmp = randint(2);
  1781.         for (i = yval - 1; i <= yval + 1; i++) {
  1782.         c_ptr = &cave[i][xval - 5 - tmp];
  1783.         for (j = xval - 5 - tmp; j <= xval - 3 - tmp; j++) {
  1784.             c_ptr->fval = TMP1_WALL;
  1785.             c_ptr++;
  1786.         }
  1787.         }
  1788.         for (i = yval - 1; i <= yval + 1; i++) {
  1789.         c_ptr = &cave[i][xval + 3 + tmp];
  1790.         for (j = xval + 3 + tmp; j <= xval + 5 + tmp; j++) {
  1791.             c_ptr->fval = TMP1_WALL;
  1792.             c_ptr++;
  1793.         }
  1794.         }
  1795.     }
  1796.     if (randint(3) == 1) {       /* Inner rooms     */
  1797.         c_ptr = &cave[yval - 1][xval - 5];
  1798.         d_ptr = &cave[yval + 1][xval - 5];
  1799.         for (i = xval - 5; i <= xval + 5; i++) {
  1800.         c_ptr->fval = TMP1_WALL;
  1801.         c_ptr++;
  1802.         d_ptr->fval = TMP1_WALL;
  1803.         d_ptr++;
  1804.         }
  1805.         cave[yval][xval - 5].fval = TMP1_WALL;
  1806.         cave[yval][xval + 5].fval = TMP1_WALL;
  1807.         place_secret_door(yval - 3 + (randint(2) << 1), xval - 3);
  1808.         place_secret_door(yval - 3 + (randint(2) << 1), xval + 3);
  1809.         object_level = dun_level;
  1810.         if (randint(3) == 1)
  1811.         place_object(yval, xval - 2);
  1812.         if (randint(3) == 1)
  1813.         place_object(yval, xval + 2);
  1814.         vault_monster(yval, xval - 2, randint(2));
  1815.         vault_monster(yval, xval + 2, randint(2));
  1816.     }
  1817.     break;
  1818.  
  1819.       case 4:               /* Maze inside.     */
  1820.     tmp = randint(4);
  1821.     if (tmp < 3) {           /* Place a door     */
  1822.         if (tmp == 1)
  1823.         place_secret_door(y_height - 1, xval);
  1824.         else
  1825.         place_secret_door(y_depth + 1, xval);
  1826.     } else {
  1827.         if (tmp == 3)
  1828.         place_secret_door(yval, x_left - 1);
  1829.         else
  1830.         place_secret_door(yval, x_right + 1);
  1831.     }
  1832.  
  1833.     for (i = y_height; i <= y_depth; i++)
  1834.         for (j = x_left; j <= x_right; j++)
  1835.         if (0x1 & (j + i))
  1836.             cave[i][j].fval = TMP1_WALL;
  1837.  
  1838.     /* Monsters just love mazes.         */
  1839.     vault_monster(yval, xval - 5, randint(3));
  1840.     vault_monster(yval, xval + 5, randint(3));
  1841.     /* Traps make them entertaining.     */
  1842.     vault_trap(yval, xval - 3, 2, 8, randint(3));
  1843.     vault_trap(yval, xval + 3, 2, 8, randint(3));
  1844.     /* Mazes should have some treasure too..     */
  1845.     for (i = 0; i < 3; i++)
  1846.         random_object(yval, xval, 1);
  1847.     break;
  1848.  
  1849.       case 5:               /* Four small rooms.     */
  1850.     for (i = y_height; i <= y_depth; i++)
  1851.         cave[i][xval].fval = TMP1_WALL;
  1852.  
  1853.     c_ptr = &cave[yval][x_left];
  1854.     for (i = x_left; i <= x_right; i++) {
  1855.         c_ptr->fval = TMP1_WALL;
  1856.         c_ptr++;
  1857.     }
  1858.  
  1859.     if (randint(2) == 1) {
  1860.         i = randint(10);
  1861.         place_secret_door(y_height - 1, xval - i);
  1862.         place_secret_door(y_height - 1, xval + i);
  1863.         place_secret_door(y_depth + 1, xval - i);
  1864.         place_secret_door(y_depth + 1, xval + i);
  1865.     } else {
  1866.         i = randint(3);
  1867.         place_secret_door(yval + i, x_left - 1);
  1868.         place_secret_door(yval - i, x_left - 1);
  1869.         place_secret_door(yval + i, x_right + 1);
  1870.         place_secret_door(yval - i, x_right + 1);
  1871.     }
  1872.  
  1873.     /* Treasure in each one.         */
  1874.     random_object(yval, xval, 2 + randint(2));
  1875.     /* Gotta have some monsters.         */
  1876.     vault_monster(yval + 2, xval - 4, randint(2));
  1877.     vault_monster(yval + 2, xval + 4, randint(2));
  1878.     vault_monster(yval - 2, xval - 4, randint(2));
  1879.     vault_monster(yval - 2, xval + 4, randint(2));
  1880.     break;
  1881.     }
  1882. }
  1883.  
  1884. /* Builds a room at a row, column coordinate        -RAK-     */
  1885. /* Type 3 unusual rooms are cross shaped             */
  1886. static void 
  1887. build_type3(yval, xval)
  1888. int yval, xval;
  1889. {
  1890.     int                 y_height, y_depth;
  1891.     int                 x_left, x_right;
  1892.     register int        tmp, i, j;
  1893.     int8u               floor;
  1894.     register cave_type *c_ptr;
  1895.  
  1896. /* quick, basic bounds-check... If too close, then this is better suited to a
  1897.  * simpler room type. -CFT 
  1898.  */
  1899.     if (!in_bounds(yval - 3, xval - 3) || !in_bounds(yval + 3, xval + 3)) {
  1900.     build_type1(yval, xval);
  1901.     return;
  1902.     }
  1903.     if (dun_level <= randint(25))
  1904.     floor = LIGHT_FLOOR;       /* Floor with light     */
  1905.     else
  1906.     floor = DARK_FLOOR;       /* Dark floor     */
  1907.     tmp = 2 + randint(2);
  1908.     y_height = yval - tmp;
  1909.     y_depth = yval + tmp;
  1910.     x_left = xval - 1;
  1911.     x_right = xval + 1;
  1912.  
  1913. /* for paranoia's sake: bounds-check!  Memory errors caused by accessing
  1914.  * cave[][] out-of-bounds are nearly impossible to spot!  -CFT 
  1915.  */
  1916.     if (y_height < 1)
  1917.     y_height = 1;
  1918.     if (y_depth >= (cur_height - 1))
  1919.     y_depth = cur_height - 2;
  1920.     for (i = y_height; i <= y_depth; i++)
  1921.     for (j = x_left; j <= x_right; j++) {
  1922.         c_ptr = &cave[i][j];
  1923.         c_ptr->fval = floor;
  1924.         c_ptr->lr = TRUE;
  1925.     }
  1926.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  1927.     c_ptr = &cave[i][x_left - 1];
  1928.     c_ptr->fval = GRANITE_WALL;
  1929.     c_ptr->lr = TRUE;
  1930.     c_ptr = &cave[i][x_right + 1];
  1931.     c_ptr->fval = GRANITE_WALL;
  1932.     c_ptr->lr = TRUE;
  1933.     }
  1934.     for (i = x_left; i <= x_right; i++) {
  1935.     c_ptr = &cave[y_height - 1][i];
  1936.     c_ptr->fval = GRANITE_WALL;
  1937.     c_ptr->lr = TRUE;
  1938.     c_ptr = &cave[y_depth + 1][i];
  1939.     c_ptr->fval = GRANITE_WALL;
  1940.     c_ptr->lr = TRUE;
  1941.     }
  1942.     tmp = 2 + randint(9);
  1943.     y_height = yval - 1;
  1944.     y_depth = yval + 1;
  1945.     x_left = xval - tmp;
  1946.     x_right = xval + tmp;
  1947.  
  1948. /* for paranoia's sake: bounds-check!  Memory errors caused by accessing
  1949.  * cave[][] out-of-bounds are nearly impossible to spot!  -CFT 
  1950.  */
  1951.  
  1952.     if (x_left < 1)
  1953.     x_left = 1;
  1954.     if (x_right >= (cur_width - 1))
  1955.     x_right = cur_width - 2;
  1956.  
  1957.     for (i = y_height; i <= y_depth; i++)
  1958.     for (j = x_left; j <= x_right; j++) {
  1959.         c_ptr = &cave[i][j];
  1960.         c_ptr->fval = floor;
  1961.         c_ptr->lr = TRUE;
  1962.     }
  1963.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  1964.     c_ptr = &cave[i][x_left - 1];
  1965.     if (c_ptr->fval != floor) {
  1966.         c_ptr->fval = GRANITE_WALL;
  1967.         c_ptr->lr = TRUE;
  1968.     }
  1969.     c_ptr = &cave[i][x_right + 1];
  1970.     if (c_ptr->fval != floor) {
  1971.         c_ptr->fval = GRANITE_WALL;
  1972.         c_ptr->lr = TRUE;
  1973.     }
  1974.     }
  1975.     for (i = x_left; i <= x_right; i++) {
  1976.     c_ptr = &cave[y_height - 1][i];
  1977.     if (c_ptr->fval != floor) {
  1978.         c_ptr->fval = GRANITE_WALL;
  1979.         c_ptr->lr = TRUE;
  1980.     }
  1981.     c_ptr = &cave[y_depth + 1][i];
  1982.     if (c_ptr->fval != floor) {
  1983.         c_ptr->fval = GRANITE_WALL;
  1984.         c_ptr->lr = TRUE;
  1985.     }
  1986.     }
  1987. /* Special features.             */
  1988.     switch (randint(4)) {
  1989.       case 1:               /* Large middle pillar         */
  1990.     for (i = yval - 1; i <= yval + 1; i++) {
  1991.         c_ptr = &cave[i][xval - 1];
  1992.         for (j = xval - 1; j <= xval + 1; j++) {
  1993.         c_ptr->fval = TMP1_WALL;
  1994.         c_ptr++;
  1995.         }
  1996.     }
  1997.     break;
  1998.  
  1999.       case 2:               /* Inner treasure vault         */
  2000.     for (i = yval - 1; i <= yval + 1; i++) {
  2001.         cave[i][xval - 1].fval = TMP1_WALL;
  2002.         cave[i][xval + 1].fval = TMP1_WALL;
  2003.     }
  2004.     cave[yval - 1][xval].fval = TMP1_WALL;
  2005.     cave[yval + 1][xval].fval = TMP1_WALL;
  2006.  
  2007.     tmp = randint(4);       /* Place a door     */
  2008.     if (tmp < 3)
  2009.         place_secret_door(yval - 3 + (tmp << 1), xval);
  2010.     else
  2011.         place_secret_door(yval, xval - 7 + (tmp << 1));
  2012.  
  2013.     /* Place a treasure in the vault         */
  2014.     object_level = dun_level;
  2015.     place_object(yval, xval);
  2016.     /* Let's guard the treasure well.     */
  2017.     vault_monster(yval, xval, 2 + randint(2));
  2018.     /* Traps naturally             */
  2019.     vault_trap(yval, xval, 4, 4, 1 + randint(3));
  2020.     break;
  2021.  
  2022.       case 3:
  2023.     if (randint(3) == 1) {
  2024.         cave[yval - 1][xval - 2].fval = TMP1_WALL;
  2025.         cave[yval + 1][xval - 2].fval = TMP1_WALL;
  2026.         cave[yval - 1][xval + 2].fval = TMP1_WALL;
  2027.         cave[yval + 1][xval + 2].fval = TMP1_WALL;
  2028.         cave[yval - 2][xval - 1].fval = TMP1_WALL;
  2029.         cave[yval - 2][xval + 1].fval = TMP1_WALL;
  2030.         cave[yval + 2][xval - 1].fval = TMP1_WALL;
  2031.         cave[yval + 2][xval + 1].fval = TMP1_WALL;
  2032.         if (randint(3) == 1) {
  2033.         place_secret_door(yval, xval - 2);
  2034.         place_secret_door(yval, xval + 2);
  2035.         place_secret_door(yval - 2, xval);
  2036.         place_secret_door(yval + 2, xval);
  2037.         }
  2038.     } else if (randint(3) == 1) {
  2039.         cave[yval][xval].fval = TMP1_WALL;
  2040.         cave[yval - 1][xval].fval = TMP1_WALL;
  2041.         cave[yval + 1][xval].fval = TMP1_WALL;
  2042.         cave[yval][xval - 1].fval = TMP1_WALL;
  2043.         cave[yval][xval + 1].fval = TMP1_WALL;
  2044.     } else if (randint(3) == 1)
  2045.         cave[yval][xval].fval = TMP1_WALL;
  2046.     break;
  2047.  
  2048.       case 4:
  2049.     break;
  2050.     }
  2051. }
  2052.  
  2053. static void 
  2054. vault_nasty(j, i, type, rank, colour)
  2055. int j, i, type, rank, colour;
  2056. {
  2057.     switch (type) {
  2058.       case 1:
  2059.     vault_jelly(j, i);
  2060.     break;
  2061.       case 2:
  2062.     vault_orc(j, i, rank);
  2063.     break;
  2064.       case 3:
  2065.     vault_troll(j, i, rank);
  2066.     break;
  2067.       case 4:
  2068.     vault_undead(j, i);
  2069.     break;
  2070.       case 5:
  2071.     vault_dragon(j, i, rank, colour);
  2072.     break;
  2073.       case 6:
  2074.     vault_demon(j, i, rank);
  2075.     break;
  2076.       case 7:
  2077.     vault_giant(j, i, rank);
  2078.     break;
  2079.     }
  2080. }
  2081.  
  2082. static void 
  2083. special_pit(yval, xval, type)
  2084. int yval, xval, type;
  2085. {
  2086.     register int        i, j, y_height, x_left;
  2087.     int                 y_depth, x_right, colour;
  2088.     int8u               floor;
  2089.     register cave_type *c_ptr, *d_ptr;
  2090.  
  2091.     floor = DARK_FLOOR;
  2092.     y_height = yval - 4;
  2093.     y_depth = yval + 4;
  2094.     x_left = xval - 11;
  2095.     x_right = xval + 11;
  2096.  
  2097.     /* for paranoia's sake: bounds-check!  Memory errors caused by
  2098.      * accessing cave[][] out-of-bounds are nearly impossible to
  2099.      * spot!  -CFT */
  2100.     if ((y_height < 1) || (y_depth >= (cur_height-1)) ||
  2101.     (x_left < 1) || (x_right >= (cur_width-1))) {
  2102.     build_type1(yval,xval); /* type1 is heavily bounds-checked, and considered
  2103.                  * safe to use as a fall-back room type -CFT */
  2104.     return;
  2105.     } else
  2106.     if ((randint(dun_level*dun_level + 1) < 300) && (dun_level <= 40))
  2107.         good_item_flag = TRUE;
  2108.  
  2109. /* the x dim of rooms tends to be much larger than the y dim, so don't bother
  2110.  * rewriting the y loop 
  2111.  */
  2112.  
  2113.     for (i = y_height; i <= y_depth; i++) {
  2114.     c_ptr = &cave[i][x_left];
  2115.     for (j = x_left; j <= x_right; j++) {
  2116.         c_ptr->fval = floor;
  2117.         c_ptr->lr = TRUE;
  2118.         c_ptr++;
  2119.     }
  2120.     }
  2121.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  2122.     c_ptr = &cave[i][x_left - 1];
  2123.     c_ptr->fval = GRANITE_WALL;
  2124.     c_ptr->lr = TRUE;
  2125.     c_ptr = &cave[i][x_right + 1];
  2126.     c_ptr->fval = GRANITE_WALL;
  2127.     c_ptr->lr = TRUE;
  2128.     }
  2129.     c_ptr = &cave[y_height - 1][x_left];
  2130.     d_ptr = &cave[y_depth + 1][x_left];
  2131.     for (i = x_left; i <= x_right; i++) {
  2132.     c_ptr->fval = GRANITE_WALL;
  2133.     c_ptr->lr = TRUE;
  2134.     c_ptr++;
  2135.     d_ptr->fval = GRANITE_WALL;
  2136.     d_ptr->lr = TRUE;
  2137.     d_ptr++;
  2138.     }
  2139. /* The inner room         */
  2140.     y_height = y_height + 2;
  2141.     y_depth = y_depth - 2;
  2142.     x_left = x_left + 2;
  2143.     x_right = x_right - 2;
  2144.     for (i = (y_height - 1); i <= (y_depth + 1); i++) {
  2145.     cave[i][x_left - 1].fval = TMP1_WALL;
  2146.     cave[i][x_right + 1].fval = TMP1_WALL;
  2147.     }
  2148.     c_ptr = &cave[y_height - 1][x_left];
  2149.     d_ptr = &cave[y_depth + 1][x_left];
  2150.     for (i = x_left; i <= x_right; i++) {
  2151.     c_ptr->fval = TMP1_WALL;
  2152.     c_ptr++;
  2153.     d_ptr->fval = TMP1_WALL;
  2154.     d_ptr++;
  2155.     }
  2156.     switch (randint(4)) {
  2157.       case 1:
  2158.     place_secret_door(y_height - 1, xval);
  2159.     break;
  2160.       case 2:
  2161.     place_secret_door(y_depth + 1, xval);
  2162.     break;
  2163.       case 3:
  2164.     place_secret_door(yval, x_left - 1);
  2165.     break;
  2166.       case 4:
  2167.     place_secret_door(yval, x_right + 1);
  2168.     break;
  2169.     }
  2170.     colour = randint(6);
  2171.     if (wizard || peek) {
  2172.     switch (type) {
  2173.       case 1:
  2174.         msg_print("A Slime Pit");
  2175.         break;
  2176.       case 2:
  2177.         msg_print("An Orc Pit");
  2178.         break;
  2179.       case 3:
  2180.         msg_print("A Troll Pit");
  2181.         break;
  2182.       case 4:
  2183.         msg_print("A Graveyard");
  2184.         break;
  2185.       case 5:
  2186.         switch (colour) {
  2187.           case 1:
  2188.         msg_print("A Blue Dragon Pit");
  2189.         break;
  2190.           case 2:
  2191.         msg_print("A White Dragon Pit");
  2192.         break;
  2193.           case 3:
  2194.         msg_print("A Green Dragon Pit");
  2195.         break;
  2196.           case 4:
  2197.         msg_print("A Black Dragon Pit");
  2198.         break;
  2199.           case 5:
  2200.         msg_print("A Red Dragon Pit");
  2201.         break;
  2202.           case 6:
  2203.         msg_print("A Multi-Hued Dragon Pit");
  2204.         break;
  2205.         }
  2206.         break;
  2207.       case 6:
  2208.         msg_print("A Demon Pit");
  2209.         break;
  2210.       case 7:
  2211.         msg_print("A Giant Pit");
  2212.         break;
  2213.     }
  2214.     }
  2215.     j = y_height;
  2216.     for (i = x_left; i <= x_right; i++)
  2217.     vault_nasty(j, i, type, 1, colour);
  2218.     j = y_depth;
  2219.     for (i = x_left; i <= x_right; i++)
  2220.     vault_nasty(j, i, type, 1, colour);
  2221.     i = x_left;
  2222.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2223.     vault_nasty(j, i, type, 1, colour);
  2224.     i = x_right;
  2225.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2226.     vault_nasty(j, i, type, 1, colour);
  2227.     i = x_left + 1;
  2228.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2229.     vault_nasty(j, i, type, 2, colour);
  2230.     i = x_left + 2;
  2231.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2232.     vault_nasty(j, i, type, 2, colour);
  2233.     i = x_right - 1;
  2234.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2235.     vault_nasty(j, i, type, 2, colour);
  2236.     i = x_right - 2;
  2237.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2238.     vault_nasty(j, i, type, 2, colour);
  2239.     i = x_left + 3;
  2240.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2241.     vault_nasty(j, i, type, 3, colour);
  2242.     i = x_left + 4;
  2243.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2244.     vault_nasty(j, i, type, 3, colour);
  2245.     i = x_right - 3;
  2246.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2247.     vault_nasty(j, i, type, 3, colour);
  2248.     i = x_right - 4;
  2249.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2250.     vault_nasty(j, i, type, 3, colour);
  2251.     i = x_left + 5;
  2252.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2253.     vault_nasty(j, i, type, 4, colour);
  2254.     i = x_left + 6;
  2255.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2256.     vault_nasty(j, i, type, 4, colour);
  2257.     i = x_right - 5;
  2258.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2259.     vault_nasty(j, i, type, 4, colour);
  2260.     i = x_right - 6;
  2261.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2262.     vault_nasty(j, i, type, 4, colour);
  2263.     i = x_left + 7;
  2264.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2265.     vault_nasty(j, i, type, 5, colour);
  2266.     i = x_left + 8;
  2267.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2268.     vault_nasty(j, i, type, 5, colour);
  2269.     i = x_right - 7;
  2270.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2271.     vault_nasty(j, i, type, 5, colour);
  2272.     i = x_right - 8;
  2273.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2274.     vault_nasty(j, i, type, 5, colour);
  2275.     i = x_right - 9;
  2276.     for (j = (y_height + 1); j <= (y_depth - 1); j++)
  2277.     vault_nasty(j, i, type, 6, colour);
  2278. }
  2279.  
  2280. /* Constructs a tunnel between two points         */
  2281. static void 
  2282. build_tunnel(row1, col1, row2, col2)
  2283. int row1, col1, row2, col2;
  2284. {
  2285.     register int        tmp_row, tmp_col, i, j;
  2286.     register cave_type *c_ptr;
  2287.     cave_type          *d_ptr;
  2288.     coords              tunstk[1000], wallstk[1000];
  2289.     coords             *tun_ptr;
  2290.     int                 row_dir, col_dir, tunindex, wallindex;
  2291.     int                 stop_flag, door_flag, main_loop_count;
  2292.     int                 start_row, start_col;
  2293.  
  2294. /* Main procedure for Tunnel             */
  2295. /* Note: 9 is a temporary value         */
  2296.     stop_flag = FALSE;
  2297.     door_flag = FALSE;
  2298.     tunindex = 0;
  2299.     wallindex = 0;
  2300.     main_loop_count = 0;
  2301.     start_row = row1;
  2302.     start_col = col1;
  2303.     correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
  2304.  
  2305.     do {
  2306.     /* prevent infinite loops, just in case */
  2307.     main_loop_count++;
  2308.     if (main_loop_count > 2000)
  2309.         stop_flag = TRUE;
  2310.  
  2311.     if (randint(100) > DUN_TUN_CHG) {
  2312.         if (randint(DUN_TUN_RND) == 1)
  2313.         rand_dir(&row_dir, &col_dir);
  2314.         else
  2315.         correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
  2316.     }
  2317.     tmp_row = row1 + row_dir;
  2318.     tmp_col = col1 + col_dir;
  2319.     while (!in_bounds(tmp_row, tmp_col)) {
  2320.         if (randint(DUN_TUN_RND) == 1)
  2321.         rand_dir(&row_dir, &col_dir);
  2322.         else
  2323.         correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
  2324.         tmp_row = row1 + row_dir;
  2325.         tmp_col = col1 + col_dir;
  2326.     }
  2327.     c_ptr = &cave[tmp_row][tmp_col];
  2328.     if (c_ptr->fval == NULL_WALL) {
  2329.         row1 = tmp_row;
  2330.         col1 = tmp_col;
  2331.         if (tunindex < 1000) {
  2332.         tunstk[tunindex].y = row1;
  2333.         tunstk[tunindex].x = col1;
  2334.         tunindex++;
  2335.         }
  2336.         door_flag = FALSE;
  2337.     } else if (c_ptr->fval == TMP2_WALL)
  2338.     /* do nothing */
  2339.         ;
  2340.     else if (c_ptr->fval == GRANITE_WALL) {
  2341.         d_ptr = &cave[tmp_row + row_dir][tmp_col + col_dir];
  2342.         if ((d_ptr->fval == GRANITE_WALL) || (d_ptr->fval == TMP2_WALL))
  2343.         c_ptr->fval = TMP2_WALL;
  2344.  
  2345.     /* if can not pass completely through wall don't try... And mark as
  2346.      * impassible for future -KOC 
  2347.      */
  2348.         else {
  2349.         row1 = tmp_row;
  2350.         col1 = tmp_col;
  2351.         if (wallindex < 1000) {
  2352.             wallstk[wallindex].y = row1;
  2353.             wallstk[wallindex].x = col1;
  2354.             wallindex++;
  2355.         }
  2356.         for (i = row1 - 1; i <= row1 + 1; i++)
  2357.             for (j = col1 - 1; j <= col1 + 1; j++)
  2358.             if (in_bounds(i, j)) {
  2359.                 d_ptr = &cave[i][j];
  2360.             /*
  2361.              * values 11 and 12 are impossible here,
  2362.              * place_streamer is never run before build_tunnel 
  2363.              */
  2364.                 if (d_ptr->fval == GRANITE_WALL)
  2365.                 d_ptr->fval = TMP2_WALL;
  2366.             }
  2367.         }
  2368.     } else if (c_ptr->fval == CORR_FLOOR || c_ptr->fval == BLOCKED_FLOOR) {
  2369.         row1 = tmp_row;
  2370.         col1 = tmp_col;
  2371.         if (!door_flag) {
  2372.         if (doorindex < 100) {
  2373.             doorstk[doorindex].y = row1;
  2374.             doorstk[doorindex].x = col1;
  2375.             doorindex++;
  2376.         }
  2377.         door_flag = TRUE;
  2378.         }
  2379.  
  2380.         /* make sure that tunnel has gone a reasonable distance before
  2381.          * stopping it, this helps prevent isolated rooms 
  2382.          */
  2383.         if (randint(100) > DUN_TUN_CON) {
  2384.         tmp_row = row1 - start_row;
  2385.         if (tmp_row < 0)
  2386.             tmp_row = (-tmp_row);
  2387.         tmp_col = col1 - start_col;
  2388.         if (tmp_col < 0)
  2389.             tmp_col = (-tmp_col);
  2390.         if (tmp_row > 10 || tmp_col > 10)
  2391.             stop_flag = TRUE;
  2392.         }
  2393.     } else {           /* c_ptr->fval != NULL, TMP2, GRANITE,
  2394.                     * CORR */
  2395.         row1 = tmp_row;
  2396.         col1 = tmp_col;
  2397.     }
  2398.     }
  2399.     while (((row1 != row2) || (col1 != col2)) && (!stop_flag));
  2400.  
  2401.     tun_ptr = &tunstk[0];
  2402.     for (i = 0; i < tunindex; i++) {
  2403.     d_ptr = &cave[tun_ptr->y][tun_ptr->x];
  2404.     d_ptr->fval = CORR_FLOOR;
  2405.     tun_ptr++;
  2406.     }
  2407.     for (i = 0; i < wallindex; i++) {
  2408.     c_ptr = &cave[wallstk[i].y][wallstk[i].x];
  2409.     if (c_ptr->fval == TMP2_WALL) {
  2410.         if (randint(100) < DUN_TUN_PEN)
  2411.         place_door(wallstk[i].y, wallstk[i].x);
  2412.         else {
  2413.         /* these have to be doorways to rooms */
  2414.         c_ptr->fval = CORR_FLOOR;
  2415.         }
  2416.     }
  2417.     }
  2418. }
  2419.  
  2420.  
  2421. static int 
  2422. next_to(y, x)
  2423. register int y, x;
  2424. {
  2425.     register int next;
  2426.  
  2427.     if (!in_bounds(y, x))
  2428.     return 0;           /* abort! -CFT */
  2429.     if (next_to_corr(y, x) > 2)
  2430.     if ((cave[y - 1][x].fval >= MIN_CAVE_WALL)
  2431.         && (cave[y + 1][x].fval >= MIN_CAVE_WALL))
  2432.         next = TRUE;
  2433.     else if ((cave[y][x - 1].fval >= MIN_CAVE_WALL)
  2434.          && (cave[y][x + 1].fval >= MIN_CAVE_WALL))
  2435.         next = TRUE;
  2436.     else
  2437.         next = FALSE;
  2438.     else
  2439.     next = FALSE;
  2440.     return (next);
  2441. }
  2442.  
  2443. /* Places door at y, x position if at least 2 walls found     */
  2444. static void 
  2445. try_door(y, x)
  2446. register int y, x;
  2447. {
  2448.     if (!in_bounds(y, x))
  2449.     return;               /* abort! -CFT */
  2450.     if ((cave[y][x].fval == CORR_FLOOR) && (randint(100) > DUN_TUN_JCT)
  2451.     && next_to(y, x))
  2452.     place_door(y, x);
  2453. }
  2454.  
  2455.  
  2456. /* Returns random co-ordinates                -RAK-     */
  2457. static void 
  2458. new_spot(y, x)
  2459. int16 *y, *x;
  2460. {
  2461.     register int        i, j;
  2462.     register cave_type *c_ptr;
  2463.  
  2464.     do {
  2465.     i = randint(cur_height - 2);
  2466.     j = randint(cur_width - 2);
  2467.     c_ptr = &cave[i][j];
  2468.     }
  2469.     while (c_ptr->fval >= MIN_CLOSED_SPACE || (c_ptr->cptr != 0)
  2470.        || (c_ptr->tptr != 0) || (c_ptr->fval == NT_LIGHT_FLOOR)
  2471.        || (c_ptr->fval == NT_DARK_FLOOR));
  2472.     *y = i;
  2473.     *x = j;
  2474. }
  2475.  
  2476. static void 
  2477. build_pit(yval, xval)
  2478. int yval, xval;
  2479. {
  2480.     int tmp;
  2481.  
  2482.     tmp = randint(dun_level > 80 ? 80 : dun_level);
  2483.     rating += 10;
  2484.     if (tmp < 10)
  2485.     special_pit(yval, xval, 1);
  2486.     else if (tmp < 20)
  2487.     special_pit(yval, xval, 2);
  2488.     else if (tmp < 43)
  2489.     ((randint(3) == 1)
  2490.      ? special_pit(yval, xval, 7)
  2491.      : special_pit(yval, xval, 3));
  2492.     else if (tmp < 57)
  2493.     special_pit(yval, xval, 4);
  2494.     else if (tmp < 73)
  2495.     special_pit(yval, xval, 5);
  2496.     else
  2497.     special_pit(yval, xval, 6);
  2498. }
  2499.  
  2500. /* Cave logic flow for generation of new dungeon         */
  2501. static void 
  2502. cave_gen()
  2503. {
  2504.     struct spot_type {
  2505.     int endx;
  2506.     int endy;
  2507.     };
  2508.     int          room_map[20][20];
  2509.     register int i, j, k;
  2510.     int          y1, x1, y2, x2, pick1, pick2, tmp;
  2511.     int          row_rooms, col_rooms, alloc_level;
  2512.     int16        yloc[400], xloc[400];
  2513.     int          pit_ok, spec_level;
  2514.  
  2515.     rating = 0;
  2516.     spec_level = 0;
  2517.     pit_ok = FALSE;
  2518.     if ((randint(DUN_DEST) == 1) && (dun_level > 10) && (!is_quest(dun_level))) {
  2519.     if (wizard)
  2520.         msg_print("Destroyed Level");
  2521.     spec_level = SPEC_DEST;
  2522.     } else
  2523.     pit_ok = TRUE;
  2524.  
  2525.     row_rooms = 2 * (cur_height / SCREEN_HEIGHT);
  2526.     col_rooms = 2 * (cur_width / SCREEN_WIDTH);
  2527.     for (i = 0; i < row_rooms; i++)
  2528.     for (j = 0; j < col_rooms; j++)
  2529.         room_map[i][j] = FALSE;
  2530.     k = randnor(DUN_ROO_MEA, 2);
  2531.     for (i = 0; i < k; i++)
  2532.     room_map[randint(row_rooms) - 1][randint(col_rooms) - 1] = TRUE;
  2533.     k = 0;
  2534.     for (i = 0; i < row_rooms; i++)
  2535.     for (j = 0; j < col_rooms; j++)
  2536.         if (room_map[i][j] == TRUE) {
  2537.         yloc[k] = i * (SCREEN_HEIGHT >> 1) + QUART_HEIGHT;
  2538.         xloc[k] = j * (SCREEN_WIDTH >> 1) + QUART_WIDTH;
  2539.         if (dun_level > randint(DUN_UNUSUAL)) {
  2540.             tmp = randint(5);
  2541.             if ((tmp == 1) || (spec_level))
  2542.             build_type1(yloc[k], xloc[k]);
  2543.             else if (tmp == 2)
  2544.             build_type2(yloc[k], xloc[k]);
  2545.             else if (tmp == 3)
  2546.             build_type3(yloc[k], xloc[k]);
  2547.             else if ((tmp == 4) && dun_level > randint(DUN_UNUSUAL)) {
  2548.             build_type5(yloc[k], xloc[k]);
  2549.             if (j + 1 < col_rooms)
  2550.                 room_map[i][j + 1] = FALSE;
  2551.             if (j + 1 < col_rooms && i + 1 < row_rooms)
  2552.                 room_map[i + 1][j + 1] = FALSE;
  2553.             if (j > 0 && i + 1 < row_rooms)
  2554.                 room_map[i + 1][j - 1] = FALSE;
  2555.             if (i + 1 < row_rooms)
  2556.                 room_map[i + 1][j] = FALSE;
  2557.             } else if (dun_level > randint(DUN_UNUSUAL) && pit_ok) {
  2558.             build_pit(yloc[k], xloc[k]);
  2559.             pit_ok = FALSE;
  2560.             } else {
  2561.             build_room(yloc[k], xloc[k]);
  2562.             }
  2563.         } else
  2564.             build_room(yloc[k], xloc[k]);
  2565.         k++;
  2566.         }
  2567.     for (i = 0; i < k; i++) {
  2568.     pick1 = randint(k) - 1;
  2569.     pick2 = randint(k) - 1;
  2570.     y1 = yloc[pick1];
  2571.     x1 = xloc[pick1];
  2572.     yloc[pick1] = yloc[pick2];
  2573.     xloc[pick1] = xloc[pick2];
  2574.     yloc[pick2] = y1;
  2575.     xloc[pick2] = x1;
  2576.     }
  2577.     doorindex = 0;
  2578. /* move zero entry to k, so that can call build_tunnel all k times */
  2579.     yloc[k] = yloc[0];
  2580.     xloc[k] = xloc[0];
  2581.     for (i = 0; i < k; i++) {
  2582.     y1 = yloc[i];
  2583.     x1 = xloc[i];
  2584.     y2 = yloc[i + 1];
  2585.     x2 = xloc[i + 1];
  2586.     build_tunnel(y2, x2, y1, x1);
  2587.     }
  2588.     fill_cave(GRANITE_WALL);
  2589.     for (i = 0; i < DUN_STR_MAG; i++)
  2590.     place_streamer(MAGMA_WALL, DUN_STR_MC);
  2591.     for (i = 0; i < DUN_STR_QUA; i++)
  2592.     place_streamer(QUARTZ_WALL, DUN_STR_QC);
  2593.     place_boundary();
  2594. /* Place intersection doors     */
  2595.     for (i = 0; i < doorindex; i++) {
  2596.     try_door(doorstk[i].y, doorstk[i].x - 1);
  2597.     try_door(doorstk[i].y, doorstk[i].x + 1);
  2598.     try_door(doorstk[i].y - 1, doorstk[i].x);
  2599.     try_door(doorstk[i].y + 1, doorstk[i].x);
  2600.     }
  2601.     if (spec_level == SPEC_DEST)
  2602.     place_destroyed();
  2603.  
  2604.     alloc_level = (dun_level / 3);
  2605.     if (alloc_level < 2)
  2606.     alloc_level = 2;
  2607.     else if (alloc_level > 10)
  2608.     alloc_level = 10;
  2609.     place_stairs(2, randint(2) + 2, 3);
  2610.     place_stairs(1, randint(2), 3);
  2611. /* Set up the character co-ords, used by alloc_monster, place_win_monster */
  2612.     new_spot(&char_row, &char_col);
  2613.     alloc_monster((randint(8) + MIN_MALLOC_LEVEL + alloc_level), 0, TRUE);
  2614.     alloc_object(set_corr, 3, randint(alloc_level));
  2615.     alloc_object(set_room, 5, randnor(TREAS_ROOM_ALLOC, 3));
  2616.     alloc_object(set_floor, 5, randnor(TREAS_ANY_ALLOC, 3));
  2617.     alloc_object(set_floor, 4, randnor(TREAS_GOLD_ALLOC, 3));
  2618.     alloc_object(set_floor, 1, randint(alloc_level));
  2619.     if (place_ghost())
  2620.     good_item_flag = TRUE;
  2621.     else if (spec_level == SPEC_DEST) {
  2622.     int flag, counter = 0;
  2623.     do {
  2624.         flag = place_ghost();
  2625.         counter++;
  2626.     } while (!flag && counter < 10);
  2627.     if (flag)
  2628.         good_item_flag = TRUE;
  2629.     }
  2630.     if (randint(5) < 4 && dun_level >= WIN_MON_APPEAR)
  2631.     place_win_monster();
  2632. }
  2633.  
  2634.  
  2635. /* Builds a store at a row, column coordinate             */
  2636. static void 
  2637. build_store(store_num, y, x)
  2638. int store_num, y, x;
  2639. {
  2640.     int                 yval, y_height, y_depth;
  2641.     int                 xval, x_left, x_right;
  2642.     register int        i, j;
  2643.     int                 cur_pos, tmp;
  2644.     register cave_type *c_ptr;
  2645.  
  2646.     yval = y * 10 + 5;
  2647.     xval = x * 14 + 12;
  2648.     y_height = yval - randint(3);
  2649.     y_depth = yval + randint(4);
  2650.     x_left = xval - randint(4);
  2651.     x_right = xval + randint(4);
  2652.     for (i = y_height; i <= y_depth; i++)
  2653.     for (j = x_left; j <= x_right; j++)
  2654.         cave[i][j].fval = BOUNDARY_WALL;
  2655.     tmp = randint(4);
  2656.     if (tmp < 3) {
  2657.     i = randint(y_depth - y_height) + y_height - 1;
  2658.     if (tmp == 1)
  2659.         j = x_left;
  2660.     else
  2661.         j = x_right;
  2662.     } else {
  2663.     j = randint(x_right - x_left) + x_left - 1;
  2664.     if (tmp == 3)
  2665.         i = y_depth;
  2666.     else
  2667.         i = y_height;
  2668.     }
  2669.     c_ptr = &cave[i][j];
  2670.     c_ptr->fval = CORR_FLOOR;
  2671.     cur_pos = popt();
  2672.     c_ptr->tptr = cur_pos;
  2673.     invcopy(&t_list[cur_pos], OBJ_STORE_DOOR + store_num);
  2674. }
  2675.  
  2676.  
  2677. /* Link all free space in treasure list together         */
  2678. static void 
  2679. tlink()
  2680. {
  2681.     register int i;
  2682.  
  2683.     for (i = 0; i < MAX_TALLOC; i++)
  2684.     invcopy(&t_list[i], OBJ_NOTHING);
  2685.     tcptr = MIN_TRIX;
  2686. }
  2687.  
  2688.  
  2689. /* Link all free space in monster list together             */
  2690. static void 
  2691. mlink()
  2692. {
  2693.     register int i;
  2694.  
  2695.     for (i = 0; i < MAX_MALLOC; i++)
  2696.     if (m_list[i].mptr)
  2697.         delete_monster(i);
  2698.     for (i = 0; i < MAX_MALLOC; i++)
  2699.     m_list[i] = blank_monster;
  2700.     delete_unique();           /* Kludgey Fix ~Ludwig */
  2701.     mfptr = MIN_MONIX;
  2702. }
  2703.  
  2704.  
  2705. /* Town logic flow for generation of new town         */
  2706. static void 
  2707. town_gen()
  2708. {
  2709.     register int        i, j, l, m;
  2710.     register cave_type *c_ptr;
  2711.     int                 rooms[MAX_STORES], k;
  2712.  
  2713.     set_seed(town_seed);
  2714.     for (i = 0; i < MAX_STORES; i++)
  2715.     rooms[i] = i;
  2716.     l = MAX_STORES;
  2717.     for (i = 0; i < 2; i++)
  2718.     for (j = 0; j < 4; j++) {
  2719.         k = randint(l) - 1;
  2720.         build_store(rooms[k], i, j);
  2721.         for (m = k; m < l - 1; m++)
  2722.         rooms[m] = rooms[m + 1];
  2723.         l--;
  2724.     }
  2725.     fill_cave(DARK_FLOOR);
  2726. /* make stairs before reset_seed, so that they don't move around */
  2727.     place_boundary();
  2728.     place_stairs(2, 1, 0);
  2729.     reset_seed();
  2730. /* Set up the character co-ords, used by alloc_monster below */
  2731.     new_spot(&char_row, &char_col);
  2732.     if (0x1 & (turn / 5000)) {       /* Night     */
  2733.     for (i = 0; i < cur_height; i++) {
  2734.         c_ptr = &cave[i][0];
  2735.         for (j = 0; j < cur_width; j++) {
  2736.         if (c_ptr->fval != DARK_FLOOR)
  2737.             c_ptr->pl = TRUE;
  2738.         c_ptr++;
  2739.         }
  2740.     }
  2741.     alloc_monster(MIN_MALLOC_TN, 3, TRUE);
  2742.     } else {               /* Day     */
  2743.     for (i = 0; i < cur_height; i++) {
  2744.         c_ptr = &cave[i][0];
  2745.         for (j = 0; j < cur_width; j++) {
  2746.         c_ptr->pl = TRUE;
  2747.         c_ptr++;
  2748.         }
  2749.     }
  2750.     alloc_monster(MIN_MALLOC_TD, 3, TRUE);
  2751.     }
  2752.     store_maint();
  2753.     place_ghost();
  2754. }
  2755.  
  2756.  
  2757. /* Generates a random dungeon level            -RAK-     */
  2758. void 
  2759. generate_cave()
  2760. {
  2761.     panel_row_min = 0;
  2762.     panel_row_max = 0;
  2763.     panel_col_min = 0;
  2764.     panel_col_max = 0;
  2765.     char_row = (-1);
  2766.     char_col = (-1);
  2767.  
  2768.     tlink();
  2769.     mlink();
  2770.     blank_cave();
  2771.     object_level = dun_level; /* prevent great 50' levels with chars who
  2772.                                * have gone much deeper -CWS */
  2773.     if (dun_level == 0) {
  2774.     cur_height = SCREEN_HEIGHT;
  2775.     cur_width = SCREEN_WIDTH;
  2776.     max_panel_rows = (cur_height / SCREEN_HEIGHT) * 2 - 2;
  2777.     max_panel_cols = (cur_width / SCREEN_WIDTH) * 2 - 2;
  2778.     panel_row = max_panel_rows;
  2779.     panel_col = max_panel_cols;
  2780.     town_gen();
  2781.     } else {
  2782.     cur_height = MAX_HEIGHT;
  2783.     cur_width = MAX_WIDTH;
  2784.     max_panel_rows = (cur_height / SCREEN_HEIGHT) * 2 - 2;
  2785.     max_panel_cols = (cur_width / SCREEN_WIDTH) * 2 - 2;
  2786.     panel_row = max_panel_rows;
  2787.     panel_col = max_panel_cols;
  2788.     cave_gen();
  2789.     }
  2790.  
  2791.     unfelt = TRUE;
  2792.     feeling = 0;
  2793.     if (rating > 100)
  2794.     feeling = 2;
  2795.     else if (rating > 80)
  2796.     feeling = 3;
  2797.     else if (rating > 60)
  2798.     feeling = 4;
  2799.     else if (rating > 40)
  2800.     feeling = 5;
  2801.     else if (rating > 30)
  2802.     feeling = 6;
  2803.     else if (rating > 20)
  2804.     feeling = 7;
  2805.     else if (rating > 10)
  2806.     feeling = 8;
  2807.     else if (rating > 0)
  2808.     feeling = 9;
  2809.     else
  2810.     feeling = 10;
  2811.  
  2812.     if (good_item_flag)        /* do this last to explicitly set value -CWS */
  2813.     feeling = 1;
  2814. }
  2815.